Skip to content

Commit

Permalink
✨ Add md report output
Browse files Browse the repository at this point in the history
  • Loading branch information
stoe committed Mar 25, 2023
1 parent 90509c5 commit 91e216c
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 38 deletions.
21 changes: 17 additions & 4 deletions cmd/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ var (
RunE: GetActionsReport,
}

exclude = false
actionsReport utils.CSVReport
exclude = false

ActionUsesQuery struct {
RepositoryOwner struct {
Expand All @@ -66,6 +65,16 @@ var (
".yml": true,
".yaml": true,
}

actionsReport utils.CSVReport

mdActionsTemplate = `# GitHub Actions Report
| Owner | Repo | Workflow | Uses | Permissions |
| ----- | ---- | -------- | ---- | ----------- |
{{ range . }}{{ $owner := .Owner }}{{ $repo := .Repo }}{{ range .Workflows }}| {{ $owner }} | {{ $repo }} | [{{ .Path }}]({{ .URL }}) | {{ range $i, $v := .Uses }}{{ if $i }}<br/>{{ end }}[{{ $v.Action }}]({{ $v.URL }}) {{ if $v.Version }}@ ` + "`" + `{{ printf "%.7s" $v.Version }}` + "`" + `{{ end }}{{ end }} | {{ range $i, $v := .Permissions }}{{if $i }}<br/>{{ end }} ` + "`" + `{{ $v }}` + "`" + `{{ end }} |
{{ end }}{{ end }}
`
)

type (
Expand Down Expand Up @@ -119,7 +128,7 @@ type (

ActionUses struct {
Action string `json:"action"`
Version string `json:"version"`
Version string `json:"version,omitempty"`
URL string `json:"url"`
}

Expand Down Expand Up @@ -375,7 +384,11 @@ func GetActionsReport(cmd *cobra.Command, args []string) (err error) {
}

if jsonPath != "" {
utils.SaveJsonReport(jsonPath, res)
err = utils.SaveJsonReport(jsonPath, res)
}

if mdPath != "" {
err = utils.SaveMDReport(mdPath, mdActionsTemplate, res)
}

return err
Expand Down
75 changes: 54 additions & 21 deletions cmd/billing.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,16 @@ var (
storage bool

billingReport utils.CSVReport
)

func init() {
BillingCmd.PersistentFlags().BoolVar(&all, "all", true, "Get all billing data")
BillingCmd.PersistentFlags().BoolVar(&actions, "actions", false, "Get GitHub Actions billing")
BillingCmd.PersistentFlags().BoolVar(&packages, "packages", false, "Get GitHub Packages billing")
BillingCmd.PersistentFlags().BoolVar(&security, "security", false, "Get GitHub Advanced Security active committers")
BillingCmd.PersistentFlags().BoolVar(&storage, "storage", false, "Get shared storage billing")

BillingCmd.MarkFlagsMutuallyExclusive("all", "actions")
BillingCmd.MarkFlagsMutuallyExclusive("all", "packages")
BillingCmd.MarkFlagsMutuallyExclusive("all", "security")
BillingCmd.MarkFlagsMutuallyExclusive("all", "storage")

RootCmd.AddCommand(BillingCmd)
}
mdBillingTemplate = `# GitHub Billing Report
{{ $isActions := .IsActions }} {{ $isPackages := .IsPackages }} {{ $isSecurity := .IsSecurity }} {{ $isStorage := .IsStorage }}
| Organization |{{ if $isActions }} Actions |{{ end }}{{ if $isPackages }} Packages |{{ end }}{{ if $isSecurity }} Security |{{ end }}{{ if $isStorage }} Storage |{{ end }}
| ------------ |{{ if $isActions }} ------: |{{ end }}{{ if $isPackages }} -------: |{{ end }}{{ if $isSecurity }} -------: |{{ end }}{{ if $isStorage }} ------: |{{ end }}
{{ range .Data }}| {{ .Organization }} |{{ if $isActions }} {{ .ActionMinutesUsed }} |{{ end }}{{ if $isPackages }} {{ .GigabytesBandwidthUsed }} |{{ end }}{{ if $isSecurity }} {{ .AdvancedSecurityCommitters }} |{{ end }}{{ if $isStorage }} {{ .EstimatedStorageForMonth }} |{{ end }}
{{ end }}| |{{ if $isActions }}|{{ end }}{{ if $isPackages }}|{{ end }}{{ if $isSecurity }}|{{ end }}{{ if $isStorage }}|{{ end }}
| **Total** |{{ if $isActions }} **{{ .TotalActions }}** |{{ end }}{{ if $isPackages }} **{{ .TotalPackages }}** |{{ end }}{{ if $isSecurity }} **{{ .TotalSecurity }}** |{{ end }}{{ if $isStorage }} **{{ .TotalStorage }}** |{{ end }}
`
)

type (
Billing struct {
Expand Down Expand Up @@ -124,13 +118,28 @@ type (

BillingReportJSON struct {
Organization string `json:"organization"`
ActionMinutesUsed float64 `json:"action_minutes_used"`
GigabytesBandwidthUsed float64 `json:"gigabytes_bandwidth_used"`
AdvancedSecurityCommitters int `json:"advanced_security_committers"`
EstimatedStorageForMonth int `json:"estimated_storage_for_month"`
ActionMinutesUsed float64 `json:"action_minutes_used,omitempty"`
GigabytesBandwidthUsed float64 `json:"gigabytes_bandwidth_used,omitempty"`
AdvancedSecurityCommitters int `json:"advanced_security_committers,omitempty"`
EstimatedStorageForMonth int `json:"estimated_storage_for_month,omitempty"`
}
)

func init() {
BillingCmd.PersistentFlags().BoolVar(&all, "all", true, "Get all billing data")
BillingCmd.PersistentFlags().BoolVar(&actions, "actions", false, "Get GitHub Actions billing")
BillingCmd.PersistentFlags().BoolVar(&packages, "packages", false, "Get GitHub Packages billing")
BillingCmd.PersistentFlags().BoolVar(&security, "security", false, "Get GitHub Advanced Security active committers")
BillingCmd.PersistentFlags().BoolVar(&storage, "storage", false, "Get shared storage billing")

BillingCmd.MarkFlagsMutuallyExclusive("all", "actions")
BillingCmd.MarkFlagsMutuallyExclusive("all", "packages")
BillingCmd.MarkFlagsMutuallyExclusive("all", "security")
BillingCmd.MarkFlagsMutuallyExclusive("all", "storage")

RootCmd.AddCommand(BillingCmd)
}

func (c *PushDate) UnmarshalJSON(b []byte) error {
value := strings.Trim(string(b), `"`) //get rid of "

Expand Down Expand Up @@ -405,8 +414,32 @@ func GetBilling(cmd *cobra.Command, args []string) (err error) {
}

if jsonPath != "" {
utils.SaveJsonReport(jsonPath, res)
err = utils.SaveJsonReport(jsonPath, res)
}

if mdPath != "" {
err = utils.SaveMDReport(mdPath, mdBillingTemplate, struct {
Data []BillingReportJSON
IsActions bool
IsPackages bool
IsSecurity bool
IsStorage bool
TotalActions float64
TotalPackages float64
TotalSecurity int
TotalStorage int
}{
Data: res,
IsActions: actions,
IsPackages: packages,
IsSecurity: security,
IsStorage: storage,
TotalActions: actionsSum,
TotalPackages: packagesSum,
TotalSecurity: securitySum,
TotalStorage: storageSum,
})
}

return nil
return err
}
24 changes: 21 additions & 3 deletions cmd/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ var (

licenseData LicenseData
// licenseReport utils.CSVReport

mdLicenseReport = `# GitHub License Report
**Purchased**: {{ .Purchased }}
**Consumed**: {{ .Consumed }}
**Free**: {{ .Free }}
## Users
| Login | Name | Verified Emails | License Type | GitHub Enterprise Cloud User | GitHub Enterprise Server User | Visual Studio User | Accounts |
| --- | --- | --- | --- | --- | --- | --- | --: |
{{ range .Users }}| {{ .Login }} | {{ .Name }} | {{ range $i, $v := .VerifiedDomainEmails }}{{ if $i }}<br/>{{ end }}{{ $v }}{{ end }} | {{ .LicenseType }} | ` + "`" + `{{ .GHEC }}` + "`" + ` | ` + "`" + `{{ .GHES }}` + "`" + ` | ` + "`" + `{{ .VSS }}` + "`" + ` | {{ .Accounts }} |
{{ end }}
`
)

func init() {
Expand Down Expand Up @@ -99,7 +113,7 @@ type (
)

// GetLicensing returns GitHub billing information
func GetLicensing(cmd *cobra.Command, args []string) error {
func GetLicensing(cmd *cobra.Command, args []string) (err error) {
if enterprise == "" {
return fmt.Errorf("--enterprise|-e is required")
}
Expand Down Expand Up @@ -213,8 +227,12 @@ func GetLicensing(cmd *cobra.Command, args []string) error {
}

if jsonPath != "" {
utils.SaveJsonReport(jsonPath, res)
err = utils.SaveJsonReport(jsonPath, res)
}

if mdPath != "" {
err = utils.SaveMDReport(mdPath, mdLicenseReport, res)
}

return nil
return err
}
18 changes: 15 additions & 3 deletions cmd/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ var (
repositories []Repository

repoReport utils.CSVReport

mdReposReport = `# GitHub Repositories Report
| Owner | Name | Visibility | Is Archived | Is Fork | Default Branch | Disk Usage | Created At | Updated At |
| ----- | ---- | ---------- | ----------- | ------- | -------------- | ---------: | ---------- | ---------- |
{{ range . }}| {{ .Owner }} | {{ .Repo }} | {{ .Visibility }} | {{ .Archived }} | {{ .Fork }} | {{ .DefaultBranch }} | {{ .Disk }} | {{ .CreatedAt.UTC.Format "2006-01-02 15:04:05 MST" }} | {{ .UpdatedAt.UTC.Format "2006-01-02 15:04:05 MST" }} |
{{ end }}
`
)

type (
Expand Down Expand Up @@ -247,8 +255,8 @@ func GetRepos(cmd *cobra.Command, args []string) (err error) {
fmt.Sprintf("%t", repo.IsFork),
repo.DefaultBranchRef.Name,
fmt.Sprintf("%d", repo.DiskUsage),
repo.CreatedAt.Format("2006-01-02"),
repo.UpdatedAt.Format("2006-01-02"),
repo.CreatedAt.UTC().Format("2006-01-02 15:04:05 MST"),
repo.UpdatedAt.UTC().Format("2006-01-02 15:04:05 MST"),
}

res = append(res, RepoReportJSON{
Expand Down Expand Up @@ -279,7 +287,11 @@ func GetRepos(cmd *cobra.Command, args []string) (err error) {
}

if jsonPath != "" {
utils.SaveJsonReport(jsonPath, res)
err = utils.SaveJsonReport(jsonPath, res)
}

if mdPath != "" {
err = utils.SaveMDReport(mdPath, mdReposReport, res)
}

return err
Expand Down
6 changes: 4 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ var (

csvPath string
jsonPath string
mdPath string

user struct {
Login string `json:"login"`
Expand Down Expand Up @@ -136,8 +137,9 @@ func init() {
)
RootCmd.PersistentFlags().StringVar(&hostname, "hostname", "github.com", "GitHub Enterprise Server hostname")

RootCmd.PersistentFlags().StringVar(&csvPath, "csv", "", "Path to CSV file")
RootCmd.PersistentFlags().StringVar(&jsonPath, "json", "", "Path to JSON file")
RootCmd.PersistentFlags().StringVar(&csvPath, "csv", "", "Path to CSV file, to save report to file")
RootCmd.PersistentFlags().StringVar(&jsonPath, "json", "", "Path to JSON file, to save report to file")
RootCmd.PersistentFlags().StringVar(&mdPath, "md", "", "Path to MD file, to save report to file")

RootCmd.MarkFlagsMutuallyExclusive("enterprise", "owner")
RootCmd.MarkFlagsMutuallyExclusive("enterprise", "repo")
Expand Down
14 changes: 13 additions & 1 deletion cmd/verified_emails.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ var (
members []memberDetails

emailReport utils.CSVReport

mdEmailReport = `# GitHub Emails Report
| Login | Name | Email | Verified Domain Emails |
| --- | --- | --- | --- |
{{ range . }}| {{ .Login }} | {{ .Name }} | {{ .Email }} | {{ range $i, $v := .VerifiedDomainEmails }}{{ if $i }}<br/>{{ end }}{{ $v }}{{ end }} |
{{ end }}
`
)

type (
Expand Down Expand Up @@ -208,7 +216,11 @@ func GetUserEmails(cmd *cobra.Command, args []string) (err error) {
}

if jsonPath != "" {
utils.SaveJsonReport(jsonPath, res)
err = utils.SaveJsonReport(jsonPath, res)
}

if mdPath != "" {
err = utils.SaveMDReport(mdPath, mdEmailReport, res)
}

return err
Expand Down
5 changes: 3 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ Available Commands:
verified-emails List enterprise/organization members' verified emails
Flags:
--csv string Path to CSV file
--csv string Path to CSV file, to save report to file
-e, --enterprise string GitHub Enterprise Cloud account (requires read:enterprise scope)
-h, --help help for gh-report
--hostname string GitHub Enterprise Server hostname (default "github.com")
--json string Path to JSON file
--json string Path to JSON file, to save report to file
--md string Path to MD file, to save report to file
--no-cache Do not cache results for one hour (default "false")
-o, --owner string GitHub account organization (requires read:org scope) or user account (requires n/a scope)
-r, --repo string GitHub repository (owner/repo), requires repo scope
Expand Down
4 changes: 2 additions & 2 deletions utils/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"github.com/fatih/color"
)

func SaveJsonReport(p string, data interface{}) error {
func SaveJsonReport(p string, data interface{}) (err error) {
if _, err := os.Stat(filepath.Dir(p)); err != nil {
return fmt.Errorf("failed to open directory, error: %w", err)
}
Expand All @@ -47,5 +47,5 @@ func SaveJsonReport(p string, data interface{}) error {

fmt.Fprintf(color.Output, "%s %s\n", HiBlack("JSON saved to:"), p)

return nil
return err
}
58 changes: 58 additions & 0 deletions utils/md.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
Copyright © 2023 Stefan Stölzle <stefan@stoelzle.me>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package utils

import (
"fmt"
"os"
"path/filepath"
"text/template"

"github.com/fatih/color"
)

func SaveMDReport(path, tmpl string, data interface{}) (err error) {
if _, err := os.Stat(filepath.Dir(path)); err != nil {
return fmt.Errorf("failed to open directory, error: %w", err)
}

file, err := os.Create(path)
if err != nil {
return fmt.Errorf("failed to create file, error: %w", err)
}

defer file.Close()

t := template.New("report")
t, err = t.Parse(tmpl)
if err != nil {
return err
}
err = t.Execute(file, data)
if err != nil {
return err
}

fmt.Fprintf(color.Output, "%s %s\n", HiBlack("MD saved to:"), path)

return err
}
9 changes: 9 additions & 0 deletions utils/md_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package utils

import (
"testing"
)

func Test_MD(t *testing.T) {
t.Skip()
}

0 comments on commit 91e216c

Please sign in to comment.