mirror of
https://github.com/taigrr/wtf
synced 2025-01-18 04:03:14 -08:00
implemented azure devops widget
This commit is contained in:
parent
4c3abf5aca
commit
64985c3beb
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/wtfutil/wtf/modules/datadog"
|
"github.com/wtfutil/wtf/modules/datadog"
|
||||||
"github.com/wtfutil/wtf/modules/digitalclock"
|
"github.com/wtfutil/wtf/modules/digitalclock"
|
||||||
"github.com/wtfutil/wtf/modules/docker"
|
"github.com/wtfutil/wtf/modules/docker"
|
||||||
|
"github.com/wtfutil/wtf/modules/azuredevops"
|
||||||
"github.com/wtfutil/wtf/modules/feedreader"
|
"github.com/wtfutil/wtf/modules/feedreader"
|
||||||
"github.com/wtfutil/wtf/modules/gcal"
|
"github.com/wtfutil/wtf/modules/gcal"
|
||||||
"github.com/wtfutil/wtf/modules/gerrit"
|
"github.com/wtfutil/wtf/modules/gerrit"
|
||||||
@ -112,6 +113,9 @@ func MakeWidget(
|
|||||||
case "docker":
|
case "docker":
|
||||||
settings := docker.NewSettingsFromYAML(moduleName, moduleConfig, config)
|
settings := docker.NewSettingsFromYAML(moduleName, moduleConfig, config)
|
||||||
widget = docker.NewWidget(app, pages, settings)
|
widget = docker.NewWidget(app, pages, settings)
|
||||||
|
case "azuredevops":
|
||||||
|
settings := azuredevops.NewSettingsFromYAML(moduleName, moduleConfig, config)
|
||||||
|
widget = azuredevops.NewWidget(app, pages, settings)
|
||||||
case "feedreader":
|
case "feedreader":
|
||||||
settings := feedreader.NewSettingsFromYAML(moduleName, moduleConfig, config)
|
settings := feedreader.NewSettingsFromYAML(moduleName, moduleConfig, config)
|
||||||
widget = feedreader.NewWidget(app, pages, settings)
|
widget = feedreader.NewWidget(app, pages, settings)
|
||||||
|
2
go.mod
2
go.mod
@ -48,6 +48,8 @@ require (
|
|||||||
github.com/magiconair/properties v1.8.1 // indirect
|
github.com/magiconair/properties v1.8.1 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.2 // indirect
|
github.com/mattn/go-colorable v0.1.2 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.9 // indirect
|
github.com/mattn/go-isatty v0.0.9 // indirect
|
||||||
|
github.com/microsoft/azure-devops-go-api v0.0.0-20190912142452-3207b4a469d3 // indirect
|
||||||
|
github.com/microsoft/azure-devops-go-api/azuredevops v0.0.0-20190912142452-3207b4a469d3
|
||||||
github.com/mmcdole/gofeed v1.0.0-beta2.0.20190420154928-0e68beaf6fdf
|
github.com/mmcdole/gofeed v1.0.0-beta2.0.20190420154928-0e68beaf6fdf
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
|
||||||
github.com/olebedev/config v0.0.0-20190528211619-364964f3a8e4
|
github.com/olebedev/config v0.0.0-20190528211619-364964f3a8e4
|
||||||
|
5
go.sum
5
go.sum
@ -154,6 +154,7 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI
|
|||||||
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
|
||||||
@ -222,6 +223,10 @@ github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
|
|||||||
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
|
github.com/microsoft/azure-devops-go-api v0.0.0-20190912142452-3207b4a469d3 h1:FhI3QJOcd1CaXz2+DeFHUNEsS47+gxDERzVhexlTGvg=
|
||||||
|
github.com/microsoft/azure-devops-go-api v0.0.0-20190912142452-3207b4a469d3/go.mod h1:HfrxIH2ObkhL6NepJKAuEwUYY8kNvspOWDp6HDRIRQs=
|
||||||
|
github.com/microsoft/azure-devops-go-api/azuredevops v0.0.0-20190912142452-3207b4a469d3 h1:Q42uNxLRytr5ynbRkqspq37TjcfnuXwKmrS9APJv/Bw=
|
||||||
|
github.com/microsoft/azure-devops-go-api/azuredevops v0.0.0-20190912142452-3207b4a469d3/go.mod h1:PoGiBqKSQK1vIfQ+yVaFcGjDySHvym6FM1cNYnwzbrY=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mmcdole/gofeed v1.0.0-beta2.0.20190420154928-0e68beaf6fdf h1:poo3e5STwUVGyyUX0e3fHQUwT1tV8IYEFUUpYd/7LuA=
|
github.com/mmcdole/gofeed v1.0.0-beta2.0.20190420154928-0e68beaf6fdf h1:poo3e5STwUVGyyUX0e3fHQUwT1tV8IYEFUUpYd/7LuA=
|
||||||
|
59
modules/azuredevops/client.go
Normal file
59
modules/azuredevops/client.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package azuredevops
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
azrBuild "github.com/microsoft/azure-devops-go-api/azuredevops/build"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (widget *Widget) getBuildStats() string {
|
||||||
|
projName := widget.settings.projectName
|
||||||
|
statusFilter := azrBuild.BuildStatusValues.All
|
||||||
|
top := widget.settings.maxRows
|
||||||
|
builds, err := widget.cli.GetBuilds(widget.ctx, azrBuild.GetBuildsArgs{Project: &projName, StatusFilter: &statusFilter, Top: &top})
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "could not get builds").Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
result := ""
|
||||||
|
for _, build := range builds.Value {
|
||||||
|
num := *build.BuildNumber
|
||||||
|
branch := *build.SourceBranch
|
||||||
|
reason := *build.Reason
|
||||||
|
triggers := *build.TriggerInfo
|
||||||
|
if reason == azrBuild.BuildReasonValues.PullRequest {
|
||||||
|
branch = triggers["pr.sourceBranch"]
|
||||||
|
}
|
||||||
|
branch = strings.TrimPrefix(branch, "refs/heads/")
|
||||||
|
status := *build.Status
|
||||||
|
statusDisplay := "[white:grey]unknown"
|
||||||
|
if status == azrBuild.BuildStatusValues.InProgress {
|
||||||
|
statusDisplay = "[white:blue]in progress"
|
||||||
|
} else if status == azrBuild.BuildStatusValues.Cancelling {
|
||||||
|
statusDisplay = "[white:orange]in cancelling"
|
||||||
|
} else if (status == azrBuild.BuildStatusValues.Postponed) || (status == azrBuild.BuildStatusValues.NotStarted) {
|
||||||
|
statusDisplay = "[white:blue]waiting"
|
||||||
|
} else if status == azrBuild.BuildStatusValues.Completed {
|
||||||
|
buildResult := *build.Result
|
||||||
|
if buildResult == azrBuild.BuildResultValues.Succeeded {
|
||||||
|
statusDisplay = "[white:green]succeeded"
|
||||||
|
} else if buildResult == azrBuild.BuildResultValues.Failed {
|
||||||
|
statusDisplay = "[white:red]failed"
|
||||||
|
} else if buildResult == azrBuild.BuildResultValues.Canceled {
|
||||||
|
statusDisplay = "[white:darkgrey]cancelled"
|
||||||
|
} else if buildResult == azrBuild.BuildResultValues.PartiallySucceeded {
|
||||||
|
statusDisplay = "[white:magenta]partially"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += fmt.Sprintf("%s[-:-:-] #%s %s (%s) \n", statusDisplay, num, branch, reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
if result == "" {
|
||||||
|
result = "no builds found"
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
42
modules/azuredevops/example-conf.yml
Normal file
42
modules/azuredevops/example-conf.yml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
wtf:
|
||||||
|
colors:
|
||||||
|
# background: black
|
||||||
|
# foreground: blue
|
||||||
|
border:
|
||||||
|
focusable: darkslateblue
|
||||||
|
focused: orange
|
||||||
|
normal: gray
|
||||||
|
checked: yellow
|
||||||
|
highlight:
|
||||||
|
fore: black
|
||||||
|
back: gray
|
||||||
|
rows:
|
||||||
|
even: yellow
|
||||||
|
odd: white
|
||||||
|
grid:
|
||||||
|
# How _wide_ the columns are, in terminal characters. In this case we have
|
||||||
|
# four columns, each of which are 35 characters wide.
|
||||||
|
# columns: [50, ]
|
||||||
|
# How _high_ the rows are, in terminal lines. In this case we have four rows
|
||||||
|
# that support ten line of text and one of four.
|
||||||
|
# rows: [50]
|
||||||
|
refreshInterval: 1
|
||||||
|
openFileUtil: "open"
|
||||||
|
mods:
|
||||||
|
azuredevops:
|
||||||
|
type: azuredevops
|
||||||
|
title: "💻"
|
||||||
|
enabled: true
|
||||||
|
position:
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
height: 3
|
||||||
|
width: 3
|
||||||
|
refreshInterval: 1
|
||||||
|
labelColor: lightblue # title label color (optional / default: white)
|
||||||
|
apiToken: "mysecret api token" # api key (required)
|
||||||
|
orgUrl: "https://dev.azure.com/myawesomecompany/" # url to your azure devops project (required)
|
||||||
|
prjectName: "the awesome project" # name of your project (required)
|
||||||
|
maxRows: 3 #max rows to show (optional / default 3)
|
||||||
|
|
||||||
|
|
32
modules/azuredevops/settings.go
Normal file
32
modules/azuredevops/settings.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package azuredevops
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/olebedev/config"
|
||||||
|
"github.com/wtfutil/wtf/cfg"
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultTitle = "azuredevops"
|
||||||
|
|
||||||
|
// Settings defines the configuration options for this module
|
||||||
|
type Settings struct {
|
||||||
|
common *cfg.Common
|
||||||
|
labelColor string
|
||||||
|
apiToken string
|
||||||
|
orgURL string
|
||||||
|
projectName string
|
||||||
|
maxRows int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSettingsFromYAML creates and returns an instance of Settings with configuration options populated
|
||||||
|
func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings {
|
||||||
|
settings := Settings{
|
||||||
|
common: cfg.NewCommonSettingsFromModule(name, defaultTitle, ymlConfig, globalConfig),
|
||||||
|
labelColor: ymlConfig.UString("labelColor", "white"),
|
||||||
|
apiToken: ymlConfig.UString("apiToken", "api token not specified"),
|
||||||
|
orgURL: ymlConfig.UString("orgURL", "org url not specified"),
|
||||||
|
projectName: ymlConfig.UString("projectName", "project name not specified"),
|
||||||
|
maxRows: ymlConfig.UInt("maxRows", 3),
|
||||||
|
}
|
||||||
|
|
||||||
|
return &settings
|
||||||
|
}
|
66
modules/azuredevops/widget.go
Normal file
66
modules/azuredevops/widget.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package azuredevops
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
azr "github.com/microsoft/azure-devops-go-api/azuredevops"
|
||||||
|
azrBuild "github.com/microsoft/azure-devops-go-api/azuredevops/build"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/rivo/tview"
|
||||||
|
"github.com/wtfutil/wtf/view"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Widget struct {
|
||||||
|
view.TextWidget
|
||||||
|
cli *azrBuild.Client
|
||||||
|
settings *Settings
|
||||||
|
displayBuffer string
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget {
|
||||||
|
widget := Widget{
|
||||||
|
TextWidget: view.NewTextWidget(app, settings.common, false),
|
||||||
|
settings: settings,
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.View.SetScrollable(true)
|
||||||
|
connection := azr.NewPatConnection(settings.orgURL, settings.apiToken)
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
cli, err := azrBuild.NewClient(ctx, connection)
|
||||||
|
if err != nil {
|
||||||
|
widget.displayBuffer = errors.Wrap(err, "could not create client 2").Error()
|
||||||
|
} else {
|
||||||
|
widget.cli = cli
|
||||||
|
widget.ctx = ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.refreshDisplayBuffer()
|
||||||
|
|
||||||
|
return &widget
|
||||||
|
}
|
||||||
|
|
||||||
|
func (widget *Widget) Refresh() {
|
||||||
|
widget.refreshDisplayBuffer()
|
||||||
|
widget.Redraw(widget.display)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (widget *Widget) display() (string, string, bool) {
|
||||||
|
return widget.CommonSettings().Title, widget.displayBuffer, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (widget *Widget) refreshDisplayBuffer() {
|
||||||
|
if widget.cli == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.displayBuffer = ""
|
||||||
|
|
||||||
|
widget.displayBuffer += fmt.Sprintf("[%s::bul] build status - %s\n",
|
||||||
|
widget.settings.labelColor,
|
||||||
|
widget.settings.projectName)
|
||||||
|
|
||||||
|
widget.displayBuffer += widget.getBuildStats()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user