Skip to content

Commit

Permalink
feat: allow opening failed workflows (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhth authored Jan 19, 2025
1 parent 24bd983 commit b7c25d1
Show file tree
Hide file tree
Showing 14 changed files with 164 additions and 67 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ permissions:
contents: read

env:
GO_VERSION: '1.23.4'
GO_VERSION: '1.23.5'

jobs:
build:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ permissions:
contents: read

env:
GO_VERSION: '1.23.4'
GO_VERSION: '1.23.5'

jobs:
lint:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ permissions:
id-token: write

env:
GO_VERSION: '1.23.4'
GO_VERSION: '1.23.5'

jobs:
release:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/vulncheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ permissions:
contents: read

env:
GO_VERSION: '1.23.4'
GO_VERSION: '1.23.5'

jobs:
vulncheck:
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,20 @@ of two ways:

### Basic Usage

```text
Usage:
act3 [flags]
Flags:
-c string path of the config file (default "/Users/user/.config/act3/act3.yml")
-f string output format to use; possible values: default, table, html (default "default")
-t string path of the HTML template file to use
-r string repo to fetch worflows for, in the format "owner/repo"
-g bool whether to use workflows defined globally via the config file (default false)
-o bool whether to open failed workflows (via your OS's "open" command) (default false)
-h, --help help for act3
```

By default, `act3` will show results for the repository associated with the
current directory. Simply run `act3` from the project root.

Expand Down
24 changes: 19 additions & 5 deletions cmd/help.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package cmd

var (
configSampleFormat = `
import "fmt"

var configSampleFormat = `
workflows:
- id: W_kwDOLafHJ84FQglU
repo: dhth/outtasync
Expand All @@ -16,7 +17,20 @@ workflows:
name: release
key: cueitup:release
`
helpText = `Glance at the last 3 runs of your Github Actions.

Usage: act3 [flags]`
)
func getHelp(configFilePath string) string {
return fmt.Sprintf(`Glance at the last 3 runs of your Github Actions.
Usage:
act3 [flags]
Flags:
-c string path of the config file (default "%s")
-f string output format to use; possible values: default, table, html (default "default")
-t string path of the HTML template file to use
-r string repo to fetch worflows for, in the format "owner/repo"
-g bool whether to use workflows defined globally via the config file (default false)
-o bool whether to open failed workflows (via your OS's "open" command) (default false)
-h, --help help for act3
`, configFilePath)
}
33 changes: 33 additions & 0 deletions cmd/open.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cmd

import (
"fmt"
"os"

"github.com/dhth/act3/internal/gh"
"github.com/dhth/act3/internal/utils"
)

func openFailedWorkflows(results []gh.ResultData, goos string) {
var urls []string
for _, r := range results {
if r.Err != nil {
continue
}

for _, rr := range r.Result.Workflow.Runs.Nodes {
if rr.CheckSuite.IsAFailure() {
urls = append(urls, rr.URL)
}
}
}

if len(urls) == 0 {
return
}

err := utils.OpenURLsInBrowser(urls, goos)
if err != nil {
fmt.Fprintf(os.Stderr, "error opening URLs: %s", err.Error())
}
}
38 changes: 2 additions & 36 deletions cmd/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,18 @@ package cmd

import (
"fmt"
"sort"

"github.com/dhth/act3/internal/gh"
"github.com/dhth/act3/internal/types"
"github.com/dhth/act3/internal/ui"
)

func render(workflows []types.Workflow, config types.Config) error {
resultsMap := make(map[string]gh.ResultData)
resultChannel := make(chan gh.ResultData)
var results []gh.ResultData

for _, wf := range workflows {
go func(workflow types.Workflow) {
resultChannel <- gh.GetWorkflowRuns(config.GHClient, workflow)
}(wf)
}

for range workflows {
r := <-resultChannel
resultsMap[r.Workflow.ID] = r
}

if config.CurrentRepo != nil {
var resultsList []gh.ResultData
for _, r := range resultsMap {
resultsList = append(resultsList, r)
}
// sort workflows alphabetically
sort.Slice(resultsList, func(i, j int) bool {
return resultsList[i].Workflow.Name < resultsList[j].Workflow.Name
})
results = resultsList
} else {
// sort workflows in the sequence of the config file
resultsInConfigDefinedOrder := make([]gh.ResultData, len(workflows))
for i, w := range workflows {
resultsInConfigDefinedOrder[i] = resultsMap[w.ID]
}
results = resultsInConfigDefinedOrder
}

func render(results []gh.ResultData, config types.Config) error {
output, err := ui.GetOutput(config, results)
if err != nil {
return err
}

fmt.Print(output)
return nil
}
46 changes: 46 additions & 0 deletions cmd/results.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cmd

import (
"sort"

"github.com/dhth/act3/internal/gh"
"github.com/dhth/act3/internal/types"
)

func getResults(workflows []types.Workflow, config types.Config) []gh.ResultData {
resultsMap := make(map[string]gh.ResultData)
resultChannel := make(chan gh.ResultData)
var results []gh.ResultData

for _, wf := range workflows {
go func(workflow types.Workflow) {
resultChannel <- gh.GetWorkflowRuns(config.GHClient, workflow)
}(wf)
}

for range workflows {
r := <-resultChannel
resultsMap[r.Workflow.ID] = r
}

if config.CurrentRepo != nil {
var resultsList []gh.ResultData
for _, r := range resultsMap {
resultsList = append(resultsList, r)
}
// sort workflows alphabetically
sort.Slice(resultsList, func(i, j int) bool {
return resultsList[i].Workflow.Name < resultsList[j].Workflow.Name
})
results = resultsList
} else {
// sort workflows in the sequence of the config file
resultsInConfigDefinedOrder := make([]gh.ResultData, len(workflows))
for i, w := range workflows {
resultsInConfigDefinedOrder[i] = resultsMap[w.ID]
}
results = resultsInConfigDefinedOrder
}

return results
}
23 changes: 15 additions & 8 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,18 @@ var (
)

var (
format = flag.String("f", "", "output format to use; possible values: default, table, html")
htmlTemplateFile = flag.String("t", "", "path of the HTML template file to use")
global = flag.Bool("g", false, "whether to use workflows defined globally via the config file")
repo = flag.String("r", "", "repo to fetch worflows for, in the format \"owner/repo\"")
format = flag.String("f", "", "")
htmlTemplateFile = flag.String("t", "", "")
global = flag.Bool("g", false, "")
repo = flag.String("r", "", "")
openFailed = flag.Bool("o", false, "")
)

func Execute() error {
var defaultConfigDir string
var configErr error
switch runtime.GOOS {
goos := runtime.GOOS
switch goos {
case "linux", "windows":
defaultConfigDir, configErr = os.UserConfigDir()
default:
Expand All @@ -67,8 +69,7 @@ Let %s know about this via %s.
configFilePath := flag.String("c", defaultConfigFilePath, "path of the config file")

flag.Usage = func() {
fmt.Fprintf(os.Stderr, "%s\n\nFlags:\n", helpText)
flag.PrintDefaults()
fmt.Fprint(os.Stderr, getHelp(defaultConfigFilePath))
}

flag.Parse()
Expand Down Expand Up @@ -179,9 +180,15 @@ Let %s know about this via %s.
HTMLTemplate: htmlTemplate,
}

err = render(workflows, config)
results := getResults(workflows, config)

err = render(results, config)
if err != nil {
return err
}

if *openFailed {
openFailedWorkflows(results, goos)
}
return nil
}
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: '3.8'
# to test operations on linux
services:
act3-dev:
image: golang:1.23.4-alpine
image: golang:1.23.5-alpine
volumes:
- .:/go/src/app
working_dir: /go/src/app
Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/dhth/act3

go 1.23.4
go 1.23.5

require (
github.com/charmbracelet/lipgloss v1.0.0
Expand All @@ -17,16 +17,16 @@ require (
require (
dario.cat/mergo v1.0.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.1.4 // indirect
github.com/ProtonMail/go-crypto v1.1.5 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/x/ansi v0.6.0 // indirect
github.com/charmbracelet/x/ansi v0.7.0 // indirect
github.com/cli/safeexec v1.0.1 // indirect
github.com/cloudflare/circl v1.5.0 // indirect
github.com/cyphar/filepath-securejoin v0.3.6 // indirect
github.com/cyphar/filepath-securejoin v0.4.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.1 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/henvic/httpretty v0.1.4 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
Expand Down
16 changes: 8 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/ProtonMail/go-crypto v1.1.4 h1:G5U5asvD5N/6/36oIw3k2bOfBn5XVcZrb7PBjzzKKoE=
github.com/ProtonMail/go-crypto v1.1.4/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
Expand All @@ -13,8 +13,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg=
github.com/charmbracelet/lipgloss v1.0.0/go.mod h1:U5fy9Z+C38obMs+T+tJqst9VGzlOYGj4ri9reL3qUlo=
github.com/charmbracelet/x/ansi v0.6.0 h1:qOznutrb93gx9oMiGf7caF7bqqubh6YIM0SWKyA08pA=
github.com/charmbracelet/x/ansi v0.6.0/go.mod h1:KBUFw1la39nl0dLl10l5ORDAqGXaeurTQmwyyVKse/Q=
github.com/charmbracelet/x/ansi v0.7.0 h1:/QfFmiXOGGwN6fRbzvQaYp7fu1pkxpZ3qFBZWBsP404=
github.com/charmbracelet/x/ansi v0.7.0/go.mod h1:KBUFw1la39nl0dLl10l5ORDAqGXaeurTQmwyyVKse/Q=
github.com/cli/go-gh/v2 v2.11.2 h1:oad1+sESTPNTiTvh3I3t8UmxuovNDxhwLzeMHk45Q9w=
github.com/cli/go-gh/v2 v2.11.2/go.mod h1:vVFhi3TfjseIW26ED9itAR8gQK0aVThTm8sYrsZ5QTI=
github.com/cli/safeexec v1.0.1 h1:e/C79PbXF4yYTN/wauC4tviMxEV13BwljGj0N9j+N00=
Expand All @@ -23,8 +23,8 @@ github.com/cli/shurcooL-graphql v0.0.4 h1:6MogPnQJLjKkaXPyGqPRXOI2qCsQdqNfUY1QSJ
github.com/cli/shurcooL-graphql v0.0.4/go.mod h1:3waN4u02FiZivIV+p1y4d0Jo1jc6BViMA73C+sZo2fk=
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/cyphar/filepath-securejoin v0.4.0 h1:PioTG9TBRSApBpYGnDU8HC+miIsX8vitBH9LGNNMoLQ=
github.com/cyphar/filepath-securejoin v0.4.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -38,8 +38,8 @@ github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA=
github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE=
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M=
Expand Down
17 changes: 17 additions & 0 deletions internal/utils/browser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package utils

import (
"os/exec"
)

func OpenURLsInBrowser(urls []string, goos string) error {
var openCmd string
switch goos {
case "darwin":
openCmd = "open"
default:
openCmd = "xdg-open"
}
c := exec.Command(openCmd, urls...)
return c.Run()
}

0 comments on commit b7c25d1

Please sign in to comment.