aboutsummaryrefslogblamecommitdiff
path: root/cmd/ghalogs/main.go
blob: f4935f019f9613a994f616aeb2de3f7a64d39d0d (plain) (tree)










































































































































                                                                                                                                                              
package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"text/tabwriter"
	"time"

	"github.com/fcuny/world/internal/git"
	"github.com/fcuny/world/internal/terminal"
	"github.com/fcuny/world/internal/version"
)

const API_URL = "https://api.github.com"

const usage = `Usage:
    gha-log
`

type githubActionRun struct {
	Workflows []Workflow `json:"workflow_runs"`
}

type Workflow struct {
	ID           int       `json:"id"`
	Name         string    `json:"name"`
	Title        string    `json:"display_title"`
	Conclusion   string    `json:"conclusion"`
	RunStartedAt time.Time `json:"run_started_at"`
}

type Unmarshaler interface {
	UnmarshalJSON([]byte) error
}

func (w *Workflow) UnmarshalJSON(data []byte) error {
	type Alias Workflow
	aux := &struct {
		RunStartedAt string `json:"run_started_at"`
		*Alias
	}{
		Alias: (*Alias)(w),
	}
	if err := json.Unmarshal(data, &aux); err != nil {
		return err
	}
	runStartedAt, err := time.Parse(time.RFC3339, aux.RunStartedAt)
	if err != nil {
		return err
	}
	w.RunStartedAt = runStartedAt
	return nil
}

func main() {
	flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s\n", usage) }

	var (
		tokenFlag   string
		userFlag    string
		versionFlag bool
	)
	flag.StringVar(&tokenFlag, "token", "", "GitHub API token")
	flag.StringVar(&tokenFlag, "t", "", "GitHub API token")
	flag.StringVar(&userFlag, "user", "fcuny", "GitHub API token")
	flag.StringVar(&userFlag, "u", "fcuny", "GitHub API token")
	flag.BoolVar(&versionFlag, "version", false, "Print version information")
	flag.BoolVar(&versionFlag, "v", false, "Print version information")

	if versionFlag {
		information := version.VersionAndBuildInfo()
		fmt.Println(information)
		return
	}

	flag.Parse()

	if tokenFlag == "" {
		fmt.Fprintf(os.Stderr, "The API token is not set\n")
		os.Exit(1)
	}

	ctx := context.TODO()

	repositoryName, err := git.Root()
	if err != nil {
		fmt.Fprintf(os.Stderr, "could not get the repository name: %v\n", err)
		os.Exit(1)
	}

	url := fmt.Sprintf("%s/repos/%s/%s/actions/runs", API_URL, userFlag, repositoryName)
	req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
	if err != nil {
		fmt.Fprintf(os.Stderr, "could not create a request: %v\n", err)
		os.Exit(1)
	}

	req.Header.Set("Authorization", fmt.Sprintf("token %s", tokenFlag))
	req.Header.Set("Accept", "application/vnd.github.v3+json")
	req.Header.Set("X-GitHub-Api-Version", "2022-11-28")

	client := http.Client{
		Timeout: 30 * time.Second,
	}

	res, err := client.Do(req)
	if err != nil {
		fmt.Fprintf(os.Stderr, "error making http request: %s\n", err)
		os.Exit(1)
	}

	if res.StatusCode != http.StatusOK {
		fmt.Fprintf(os.Stderr, "unexpected status code: %d\n", res.StatusCode)
		os.Exit(1)
	}

	var b githubActionRun
	if err := json.NewDecoder(res.Body).Decode(&b); err != nil {
		fmt.Fprintf(os.Stderr, "error parsing the JSON response: %v\n", err)
		os.Exit(1)
	}

	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.Debug)
	for _, run := range b.Workflows {
		status := "✅"
		if run.Conclusion != "success" {
			status = "❌"
		}

		linkToAction := terminal.Link(strconv.Itoa(run.ID), fmt.Sprintf("http://github.com/%s/%s/actions/runs/%d/", userFlag, repositoryName, run.ID))
		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", linkToAction, run.Name, run.RunStartedAt.Format("2006-01-02 15:04:05"), run.Title, status)
	}
	w.Flush()
}