GoJira is a fully open source data distribution tool that connects JIRA webhooks to external services like GitHub, Discord, and Slack.
You can either download the binary relative to your operating system and fire that baby up, clone the repository and run it natively, or use docker to compose the app and it's extra goodies ( Prom, Jaeger, Redis, etc... )
The project can be run in a variety of ways, with a large array of targets (OS, docker, system, etc..)
For now the mapping for JIRA->Distribution is made from the project_map.json
file at the project root. In the future this will be better handled via sql-lite or some other in-memory datastore.
Add your project mapping to the project_map.json
file in the following format:
[
{
"ProjectKey": [
"ATEST"
],
"GitHubRepositoryName": "test_repo_a",
"DiscordChannelID": "9902741758022972"
},
{
"ProjectKey": [
"BTEST",
"CTEST"
],
"GitHubRepositoryName": "test_repo_b",
"DiscordChannelID": "599925012599"
}
]
The latest version allows mapping multiple JIRA projects to singular output channels in the case you have something like a #jira-updates
channel in Discord or Slack.
This project is ran as a Discord bot using DiscordGo, as such you will need a Discord Bot Token entered in the config.yaml
as well as proper bot permissions for your Bot to actually run.
The first half of this article walks through the proper instructions on setting up a new bot and inviting it.
Clone/fork this project and run it manually using the makefile
make run
Make sure you have your local config file set up with your environment variables first. Then either use the makefile or a custom docker command to run the project.
Makefile
make develop
Docker
docker-compose -f docker-compose.local.yml up --build
The discord bot is run with discordgo. To enable the bot to send messages in discord you will need a few things to get started. The first is setting up a bot in discord developer console which can be found here. Create your bot, give it the proper permissions to send messages/embeds, copy the Bot Token, then invite it to your server(s). The bot token should be placed in the config under discord: BotToken
. Enable the discord bot in the config then start/restart this application. The bot can be set up to filter all incoming webhook messages to one channel, or to split incoming messages into unique channels.
JIRA is the staple of this project, and this was built for personal use for digesting my own JIRA data and effectively distributing it to systems that I currently use.
See JIRA WebHooks documentation for reference to payloads here
Initially JIRA will need to be set up to send data to this service. The endpoint that accepts the JIRA data is at /v1/receiver/accept
. The incoming payload will be converted to a matching struct and the event types will be interpreted.
JIRA has a handful of event action types that it can send. It's the interpreters job to parse these actions and create a simple yet concrete decision on what to do with the parsed actions. Once the event is interpreted and an EventMap
is created its on to distribution.
The distributor has arguably the biggest lift of them all. With payload body and event map in hand it's job is to send the data to where it needs to go. Based on configurations and mappings it will decide what, where, and how to send the data. As a quick example of a simple JIRA->GitHub communication the distributor will determine: Repository->Issue|Project->IssueType|ProjectTaskType->Assignee.
OpenTelemtry is included in this project for distributed tracing. It's not absolutely necessary but in a world of integrations this is lightweight and can help seamlessly connect and trace this project when connected to others.
Example usage:
ctx, span := otel.Tracer("Receiver").Start(utils.GetRequestCtx(c), "receiverHandlers.Accept")
p := &models.JiraWebhookMessage{}
if err := c.Bind(p); err != nil {
utils.LogResponseError(c, h.logger, err)
span.End()
return c.JSON(httpErrors.ErrorResponse(err))
}
if err := h.receiverService.Accept(ctx, p); err != nil {
utils.LogResponseError(c, h.logger, err)
span.End()
return c.JSON(httpErrors.ErrorResponse(err))
}
The telemetry library used is otel
for Go. You can read more about OpenTelemetry here.
By default this project comes with the ability to spin up a separate pprof endpoint at port 5555
for debugging and taking snapshots for application insights.
By default this project comes packed with middleware that exposes a /metrics
endpoint and returns prometheus typed data. Additionally the docker compose file will also spin up a Prometheus container bound to ports 9101:9100
.
Not absolutely necessary but the docker compose will also spin up a Grafana container accessible at port 3000:3000
for use with exporting the prometheus/app metrics to create visible charts/graphs.
Originally I had included Jaeger in this build, and it still does have some remnants but with all the other observability baked in I didn't see it as absolutely necessary. If you plan on configuring this as a microservice or want to create a distributed system with this project build in Jaeger can quickly be added to the core service spin-up.
- Dan for the Idea!
- Chantel for the support!