Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stream Cirrus CI webhook events to DataDog #2

Merged
merged 10 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .cirrus.star
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
load("github.com/cirrus-modules/golang@main", "lint_task")

def main(ctx):
return [lint_task()]
32 changes: 32 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
task:
name: Release Binaries
only_if: $CIRRUS_TAG != ''
depends_on:
- Lint
env:
GITHUB_TOKEN: ENCRYPTED[!98ace8259c6024da912c14d5a3c5c6aac186890a8d4819fad78f3e0c41a4e0cd3a2537dd6e91493952fb056fa434be7c!]
container:
image: goreleaser/goreleaser:latest
cpu: 4
memory: 12G
release_script: goreleaser


docker_builder:
name: Release Docker Image
only_if: $CIRRUS_TAG != ''
depends_on:
- Lint
env:
GITHUB_TOKEN: ENCRYPTED[!82ed873afdf627284305afef4958c85a8f73127b09978a9786ac521559630ea6c9a5ab6e7f8315abf9ead09b6eff6eae!]
login_script:
- echo $GITHUB_TOKEN | docker login ghcr.io -u fkorotkov --password-stdin
setup_script:
- docker buildx create --name multibuilder
- docker buildx use multibuilder
- docker buildx inspect --bootstrap
deploy_script: |
docker buildx build --push --platform linux/amd64,linux/arm64 \
--tag ghcr.io/cirruslabs/cirrus-webhooks-server:$CIRRUS_TAG \
--tag ghcr.io/cirruslabs/cirrus-webhooks-server:latest \
.
122 changes: 122 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
run:
timeout: 5m

linters-settings:
# Even in Rust you can get away with partial matching,
# so make sure that the linter respects the programmer's
# intent expressed in the form of "default" case.
exhaustive:
default-signifies-exhaustive: true

linters:
enable:
- asciicheck
- bodyclose
- dupl
- errcheck
- exhaustive
- exportloopref
- exportloopref
- gochecknoinits
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- godox
- goerr113
- gofmt
- goheader
- gomodguard
- goprintffuncname
- gosec
- gosimple
- govet
- ineffassign
- lll
- makezero
- misspell
- nakedret
- nestif
- noctx
- nolintlint
- predeclared
- rowserrcheck
- sqlclosecheck
- staticcheck
- stylecheck
- testpackage
- tparallel
- typecheck
- unconvert
- unparam
- unused
- unused
- whitespace

disable:
# Messages like "struct of size 104 bytes could be of size 96 bytes" from a package
# that was last updated 2 years ago[1] are barely helpful.
#
# After all, we're writing the code for other people, so let's trust the compiler here (that's
# constantly evolving compared to this linter) and revisit this if memory usage becomes a problem.
#
# [1]: https://github.com/mdempsky/maligned/commit/6e39bd26a8c8b58c5a22129593044655a9e25959
- maligned

# We don't have high-performance requirements at this moment, so sacrificing
# the code readability for marginal performance gains is not worth it.
- prealloc

# New linters that require a lot of codebase churn and noise, but perhaps we can enable them in the future.
- nlreturn
- wrapcheck
- errorlint

# Unfortunately, we use globals due to how spf13/cobra works.
- gochecknoglobals

# That's fine that some Proto objects don't have all fields initialized
- exhaustivestruct

# Style linters that are total nuts.
- wsl
- gofumpt
- goimports
- funlen

# This conflicts with the Protocol Buffers Version 3 design,
# which is largely based on default values for struct fields.
- exhaustivestruct

# Enough parallelism for now.
- paralleltest

# Ill-based assumptions about identifiers like fmt.Println without taking context into account.
- forbidigo

# Advantages of using t.Helper() are too small to waste developer's cognitive stamina on it.
- thelper

# Too restrictive defaults, plus there's already a gocyclo linter in place.
- cyclop

# Gives false positives for textbook examples[1][2]
# [1]: https://github.com/charithe/durationcheck/issues/7
# [2]: https://golang.org/pkg/time/ (see "To convert an integer number of units to a Duration, multiply:")
- durationcheck

# No way to disable the "exported" check for the whole project[1]
# [1]: https://github.com/mgechev/revive/issues/244#issuecomment-560512162
- revive

# Unfortunately too much false-positives, e.g. for a 0700 umask or number 10 when using strconv.FormatInt()
- gomnd

# Needs package whitelists
- depguard

issues:
# Don't hide multiple issues that belong to one class since GitHub annotations can handle them all nicely.
max-issues-per-linter: 0
max-same-issues: 0
26 changes: 26 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
project_name: cws

before:
hooks:
- go mod download

builds:
- main: cmd/cws.go
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm64

archives:
- id: binary
format: binary
name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}"
- id: regular
name_template: "{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}"

release:
prerelease: auto
14 changes: 14 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM goreleaser/goreleaser:latest as builder

WORKDIR /build/
ADD . /build/

RUN goreleaser build --single-target --snapshot

FROM gcr.io/distroless/base

LABEL org.opencontainers.image.source=https://github.com/cirruslabs/cirrus-webhooks-server

COPY --from=builder /build/dist/cws_linux_*/cws /bin/cws

ENTRYPOINT ["/bin/cws"]
55 changes: 53 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,53 @@
# cirrus-webhooks-server-example
Example of a simple server that processes webhook events from Cirrus CI
# Cirrus Webhooks Server

Examples of the webhook event processors from the Cirrus CI.

## Datadog processor

This processor receives, enriches and streams Cirrus CI webhook events to Datadog.

### Usage

```
docker run -it --rm ghcr.io/cirruslabs/cirrus-webhooks-server:latest datadog
```

The following command-line arguments are supported:

* `--api-key` (`string`) — enables sending events via the Datadog API using the specified API key
* `--api-site` (`string`) — specifies the [Datadog site](https://docs.datadoghq.com/getting_started/site/) to use when sending events via the Datadog API (defaults to `datadoghq.com`)
* `--dogstatsd-addr` — enables sending events via the DogStatsD protocol to the specified address (for example, `--dogstatsd-addr=127.0.0.1:8125`)
* `--event-type` (`string`) — event type to process (for example `build`, `task` or `audit_event`) (defaults to `audit_event`)
* `--http-addr` (`string`) — address on which the HTTP server will listen on (defaults to `:8080`)
* `--http-path` (`string`) — HTTP path on which the webhook events will be expected (defaults to `/`)
* `--secret-token` (`string`) — if specified, this value will be used as a HMAC SHA-256 secret to verify the webhook events

### Example

The simplest way to try this processor is to use Docker and [ngrok](https://ngrok.com/).

First, obtain the API key from the Datadog's `Organization Settings` → `API Keys`.

Then, run the Datadog processor:

```sh
docker run -it --rm -p 8080:8080 ghcr.io/cirruslabs/cirrus-webhooks-server:latest datadog --api-key=$DD_API_KEY
```

Finally, [install](https://ngrok.com/download) and run `ngrok` to expose our Datadog processor's HTTP server to the internet:

```sh
ngrok http 8080
```

This will open the following TUI window:

![](docs/ngrok-http-8080.png)

You'll need to copy the forwarding address and set it in your organization's settings in the Cirrus CI app:

![](docs/cirrus-ci-webhook-settings.png)

Now you can run some tasks, and the corresponding audit events will appear shortly in your "Events Explorer":

![](docs/datadog-webhook-event.png)
22 changes: 22 additions & 0 deletions cmd/cws.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package main

import (
"context"
"github.com/cirruslabs/cirrus-webhooks-server/internal/command"
"log"
"os"
"os/signal"
)

func main() {
// Set up a signal-interruptible context
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)

// Run the command
if err := command.NewRootCmd().ExecuteContext(ctx); err != nil {
cancel()
log.Fatal(err)
}

cancel()
}
Binary file added docs/cirrus-ci-webhook-settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/datadog-webhook-event.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/ngrok-http-8080.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module github.com/cirruslabs/cirrus-webhooks-server

go 1.20

require (
github.com/DataDog/datadog-api-client-go/v2 v2.14.0
github.com/DataDog/datadog-go/v5 v5.3.0
github.com/brpaz/echozap v1.1.3
github.com/labstack/echo/v4 v4.10.2
github.com/spf13/cobra v1.7.0
go.uber.org/zap v1.24.0
)

require (
github.com/DataDog/zstd v1.5.2 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/oauth2 v0.5.0 // indirect
golang.org/x/sys v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/tools v0.11.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.1 // indirect
)
Loading