Skip to content

Commit

Permalink
Command Summary - New UI (#2671)
Browse files Browse the repository at this point in the history
  • Loading branch information
EyalDelarea authored Sep 1, 2024
1 parent e6e3c17 commit e0ea860
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 53 deletions.
106 changes: 68 additions & 38 deletions general/summary/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,13 @@ func (ms MarkdownSection) String() string {
return string(ms)
}

// Creates a summary of recorded CLI commands that were executed on the current machine.
// The summary is generated in Markdown format
// and saved in the directory stored in the JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR environment variable.
// GenerateSummaryMarkdown creates a summary of recorded CLI commands in Markdown format.
func GenerateSummaryMarkdown(c *cli.Context) error {
if !ShouldGenerateSummary() {
if !shouldGenerateSummary() {
return fmt.Errorf("unable to generate the command summary because the output directory is not specified."+
" Please ensure that the environment variable '%s' is set before running your commands to enable summary generation", coreutils.SummaryOutputDirPathEnv)
}

// Get URL and Version to generate summary links
serverUrl, majorVersion, err := extractServerUrlAndVersion(c)
if err != nil {
Expand All @@ -58,22 +57,25 @@ func GenerateSummaryMarkdown(c *cli.Context) error {
// Invoke each section's markdown generation function
for _, section := range markdownSections {
if err := invokeSectionMarkdownGeneration(section); err != nil {
log.Warn("Failed to generate markdown for section %s: %v", section, err)
log.Warn("Failed to generate markdown for section:", section, err)
}
}

// Combine all sections into a single Markdown file
finalMarkdown, err := combineMarkdownFiles()
finalMarkdown, err := mergeMarkdownFiles()
if err != nil {
return fmt.Errorf("error combining markdown files: %w", err)
}

// Saves the final Markdown to the root directory of the command summaries
return saveMarkdownToFileSystem(finalMarkdown)
}

func combineMarkdownFiles() (string, error) {
// The CLI generates summaries in sections, with each section as a separate Markdown file.
// This function merges all sections into a single Markdown file and saves it in the root of the
// command summary output directory.
func mergeMarkdownFiles() (string, error) {
var combinedMarkdown strings.Builder
// Read each section content and append it to the final Markdown
for _, section := range markdownSections {
sectionContent, err := getSectionMarkdownContent(section)
if err != nil {
Expand All @@ -86,45 +88,24 @@ func combineMarkdownFiles() (string, error) {
return combinedMarkdown.String(), nil
}

// Saves markdown content in the directory stored in the JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR environment variable.
// saveMarkdownToFileSystem saves markdown content in the specified directory.
func saveMarkdownToFileSystem(finalMarkdown string) (err error) {
if finalMarkdown == "" {
return nil
}
filePath := filepath.Join(os.Getenv(coreutils.SummaryOutputDirPathEnv), JfrogCliSummaryDir, MarkdownFileName)
file, err := os.Create(filePath)
defer func() {
err = file.Close()
}()
if err != nil {
return fmt.Errorf("error creating markdown file: %w", err)
}
defer func() {
err = errors.Join(err, file.Close())
}()
// Write to file
if _, err := file.WriteString(finalMarkdown); err != nil {
return fmt.Errorf("error writing to markdown file: %w", err)
}
return
}

func wrapCollapsibleSection(section MarkdownSection, markdown string) (string, error) {
sectionTitle, err := getSectionTitle(section)
if err != nil {
return "", err
}
return fmt.Sprintf("\n\n\n<details open>\n\n<summary> %s </summary><p></p> \n\n %s \n\n</details>\n\n\n", sectionTitle, markdown), nil
}

func getSectionTitle(section MarkdownSection) (string, error) {
switch section {
case Upload:
return "📁 Files uploaded to Artifactory by this workflow", nil
case BuildInfo:
return "📦 Artifacts published to Artifactory by this workflow", nil
case Security:
return "🔒 Security Summary", nil
default:
return "", fmt.Errorf("unknown section: %s", section)
}
return nil
}

func getSectionMarkdownContent(section MarkdownSection) (string, error) {
Expand All @@ -140,9 +121,10 @@ func getSectionMarkdownContent(section MarkdownSection) (string, error) {
if len(contentBytes) == 0 {
return "", nil
}
return wrapCollapsibleSection(section, string(contentBytes))
return string(contentBytes), nil
}

// Initiate the desired command summary implementation and invoke its Markdown generation.
func invokeSectionMarkdownGeneration(section MarkdownSection) error {
switch section {
case Security:
Expand All @@ -169,6 +151,9 @@ func generateBuildInfoMarkdown() error {
if err != nil {
return fmt.Errorf("error generating build-info markdown: %w", err)
}
if err = mapScanResults(buildInfoSummary); err != nil {
return fmt.Errorf("error mapping scan results: %w", err)
}
return buildInfoSummary.GenerateMarkdown()
}

Expand All @@ -184,7 +169,52 @@ func generateUploadMarkdown() error {
return uploadSummary.GenerateMarkdown()
}

// Upload summary should be generated only if the no build-info data exists
// mapScanResults maps the scan results saved during runtime into scan components.
func mapScanResults(commandSummary *commandsummary.CommandSummary) (err error) {
// Gets the saved scan results file paths.
indexedFiles, err := commandSummary.GetIndexedDataFilesPaths()
if err != nil {
return err
}
securityJobSummary := &securityUtils.SecurityJobSummary{}
// Init scan result map
scanResultsMap := make(map[string]commandsummary.ScanResult)
// Set default not scanned component view
scanResultsMap[commandsummary.NonScannedResult] = securityJobSummary.GetNonScannedResult()
commandsummary.StaticMarkdownConfig.SetScanResultsMapping(scanResultsMap)
// Process each scan result file by its type and append to map
for index, keyValue := range indexedFiles {
for scannedEntityName, scanResultDataFilePath := range keyValue {
scanResultsMap, err = processScan(index, scanResultDataFilePath, scannedEntityName, securityJobSummary, scanResultsMap)
if err != nil {
return
}
}
}
return
}

// Each scan result should be processed according to its index.
// To generate custom view for each scan type.
func processScan(index commandsummary.Index, filePath string, scannedName string, sec *securityUtils.SecurityJobSummary, scanResultsMap map[string]commandsummary.ScanResult) (map[string]commandsummary.ScanResult, error) {
var res commandsummary.ScanResult
var err error
switch index {
case commandsummary.DockerScan:
res, err = sec.DockerScan([]string{filePath})
case commandsummary.BuildScan:
res, err = sec.BuildScan([]string{filePath})
case commandsummary.BinariesScan:
res, err = sec.BinaryScan([]string{filePath})
}
scanResultsMap[scannedName] = res
if err != nil {
return nil, err
}
return scanResultsMap, nil
}

// shouldGenerateUploadSummary checks if upload summary should be generated.
func shouldGenerateUploadSummary() (bool, error) {
buildInfoPath := filepath.Join(os.Getenv(coreutils.SummaryOutputDirPathEnv), JfrogCliSummaryDir, string(BuildInfo))
if _, err := os.Stat(buildInfoPath); os.IsNotExist(err) {
Expand Down Expand Up @@ -225,7 +255,7 @@ func extractServerUrlAndVersion(c *cli.Context) (platformUrl string, platformMaj
return
}

// Summary should be generated only when the output directory is defined
func ShouldGenerateSummary() bool {
// shouldGenerateSummary checks if the summary should be generated.
func shouldGenerateSummary() bool {
return os.Getenv(coreutils.SummaryOutputDirPathEnv) != ""
}
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ require (
github.com/jfrog/build-info-go v1.9.35
github.com/jfrog/gofrog v1.7.5
github.com/jfrog/jfrog-cli-artifactory v0.1.6
github.com/jfrog/jfrog-cli-core/v2 v2.55.5
github.com/jfrog/jfrog-cli-core/v2 v2.55.6
github.com/jfrog/jfrog-cli-platform-services v1.3.0
github.com/jfrog/jfrog-cli-security v1.7.1
github.com/jfrog/jfrog-client-go v1.46.0
github.com/jfrog/jfrog-cli-security v1.7.2
github.com/jfrog/jfrog-client-go v1.46.1
github.com/jszwec/csvutil v1.10.0
github.com/stretchr/testify v1.9.0
github.com/testcontainers/testcontainers-go v0.33.0
Expand Down Expand Up @@ -171,12 +171,12 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)

replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240828060210-e7b37bdf5410
// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/eyaldelarea/jfrog-cli-core/v2 v2.0.0-20240829171158-7b0f89df2c0c

replace github.com/jfrog/jfrog-cli-security => github.com/attiasas/jfrog-cli-security v0.0.0-20240828061232-6cb16f5dd7ef
// replace github.com/jfrog/jfrog-cli-security => github.com/attiasas/jfrog-cli-security v0.0.0-20240829151632-3a7a90969eca

// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240806162439-01bb7dcd43fc

replace github.com/jfrog/build-info-go => github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d
// replace github.com/jfrog/build-info-go => github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d

// replace github.com/jfrog/gofrog => github.com/jfrog/gofrog dev
16 changes: 8 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -641,10 +641,6 @@ github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d h1:GS9yDbl7Moer5ODbWu+DPcQtyCYlmRL4TAdt1l+b/Vo=
github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d/go.mod h1:6mdtqjREK76bHNODXakqKR/+ksJ9dvfLS7H57BZtnLY=
github.com/attiasas/jfrog-cli-security v0.0.0-20240828061232-6cb16f5dd7ef h1:TE2MFFvWKw6SblR3yEGDftRJrIfhReix0zYMWexfFls=
github.com/attiasas/jfrog-cli-security v0.0.0-20240828061232-6cb16f5dd7ef/go.mod h1:VRMOAgJzP8JDABOJs5PU2Ph7SiutOK4NffASTdoPcq8=
github.com/beevik/etree v1.4.0 h1:oz1UedHRepuY3p4N5OjE0nK1WLCqtzHf25bxplKOHLs=
github.com/beevik/etree v1.4.0/go.mod h1:cyWiXwGoasx60gHvtnEh5x8+uIjUVnjWqBvEnhnqKDA=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
Expand Down Expand Up @@ -935,6 +931,8 @@ github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+
github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E=
github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI=
github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw=
github.com/jfrog/build-info-go v1.9.35 h1:P53Ckbuin0GYrq0LWMY0GZSptJcQwiUyW6lqTbXKdcc=
github.com/jfrog/build-info-go v1.9.35/go.mod h1:6mdtqjREK76bHNODXakqKR/+ksJ9dvfLS7H57BZtnLY=
github.com/jfrog/froggit-go v1.16.1 h1:FBIM1qevX/ag9unfmpGzfmZ36D8ulOJ+DPTSFUk3l5U=
github.com/jfrog/froggit-go v1.16.1/go.mod h1:TEJSzgiV+3D/GVGE8Y6j46ut1jrBLD1FL6WdMdKwwCE=
github.com/jfrog/gofrog v1.7.5 h1:dFgtEDefJdlq9cqTRoe09RLxS5Bxbe1Ev5+E6SmZHcg=
Expand All @@ -943,12 +941,14 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
github.com/jfrog/jfrog-cli-artifactory v0.1.6 h1:bMfJsrLQJw0dZp4nqUf1xOmtY0rpCatW/I5q88x+fhQ=
github.com/jfrog/jfrog-cli-artifactory v0.1.6/go.mod h1:jbNb22ebtupcjdhrdGq0VBew2vWG6VUK04xxGNDfynE=
github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240828060210-e7b37bdf5410 h1:nClCz6HXEH94Bw86lRYb+omzOIzq2iJMnbjiKbaVxVk=
github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20240828060210-e7b37bdf5410/go.mod h1:g+QR8lvFtu7uDbEgMcS0Vl7fwfp+1mtC2fFQRB8tv+0=
github.com/jfrog/jfrog-cli-core/v2 v2.55.6 h1:3tQuEdYgS2q7fkrrSG66OnO0S998FXGaY9BVsxSLst4=
github.com/jfrog/jfrog-cli-core/v2 v2.55.6/go.mod h1:DPO5BfWAeOByahFMMy+PcjmbPlcyoRy7Bf2C5sGKVi0=
github.com/jfrog/jfrog-cli-platform-services v1.3.0 h1:IblSDZFBjL7WLRi37Ni2DmHrXJJ6ysSMxx7t41AvyDA=
github.com/jfrog/jfrog-cli-platform-services v1.3.0/go.mod h1:Ky4SDXuMeaiNP/5zMT1YSzIuXG+cNYYOl8BaEA7Awbc=
github.com/jfrog/jfrog-client-go v1.46.0 h1:lyzJCpLN9NIp4raHw48D12+g42/Aa8SHxBbuNp4Yflk=
github.com/jfrog/jfrog-client-go v1.46.0/go.mod h1:UCu2JNBfMp9rypEmCL84DCooG79xWIHVadZQR3Ab+BQ=
github.com/jfrog/jfrog-cli-security v1.7.2 h1:Kvabj/6LhM+WEb6woIqqbv2VmIj69IFwz859Sys1Tgs=
github.com/jfrog/jfrog-cli-security v1.7.2/go.mod h1:4eztJ+gBb7Xtq/TtnOvIodBOMZutPIAZOuLxqHWXrOo=
github.com/jfrog/jfrog-client-go v1.46.1 h1:ExqOF8ClOG9LO3vbm6jTIwQHHhprbu8lxB2RrM6mMI0=
github.com/jfrog/jfrog-client-go v1.46.1/go.mod h1:UCu2JNBfMp9rypEmCL84DCooG79xWIHVadZQR3Ab+BQ=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jszwec/csvutil v1.10.0 h1:upMDUxhQKqZ5ZDCs/wy+8Kib8rZR8I8lOR34yJkdqhI=
Expand Down
2 changes: 1 addition & 1 deletion utils/cliutils/commandsflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1829,7 +1829,7 @@ var commandFlags = map[string][]string{
},
Docker: {
buildName, buildNumber, module, Project,
serverId, skipLogin, threads, detailedSummary, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly,
serverId, skipLogin, threads, detailedSummary, watches, repoPath, licenses, xrOutput, fail, ExtendedTable, BypassArchiveLimits, MinSeverity, FixableOnly, vuln,
},
DockerPush: {
buildName, buildNumber, module, Project,
Expand Down

0 comments on commit e0ea860

Please sign in to comment.