Skip to content

Commit c746ec4

Browse files
committed
🧱 QD-12546 Generate README flags and check it in CI
1 parent 406c3da commit c746ec4

File tree

9 files changed

+324
-128
lines changed

9 files changed

+324
-128
lines changed

.github/workflows/docs.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: '📖 Docs'
2+
on:
3+
pull_request:
4+
paths:
5+
- 'internal/cmd/**'
6+
- 'internal/platform/cmd/**'
7+
- 'scripts/generate-docs.go'
8+
- 'README.md'
9+
10+
jobs:
11+
check:
12+
runs-on: ubuntu-latest
13+
name: Check README.md
14+
steps:
15+
- uses: actions/checkout@v6
16+
- uses: ./.github/actions/mock-dependencies
17+
- uses: actions/setup-go@v6
18+
with:
19+
cache-dependency-path: "**/*.sum"
20+
go-version-file: go.mod
21+
- name: Check README.md is up to date
22+
run: go run scripts/generate-docs.go --check

README.md

Lines changed: 199 additions & 121 deletions
Large diffs are not rendered by default.

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ require (
4242
github.com/containerd/errdefs v1.0.0 // indirect
4343
github.com/containerd/errdefs/pkg v0.3.0 // indirect
4444
github.com/containerd/log v0.1.0 // indirect
45+
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
4546
github.com/danieljoos/wincred v1.2.2 // indirect
4647
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
4748
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
@@ -87,6 +88,7 @@ require (
8788
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
8889
github.com/prometheus/client_golang v1.11.1 // indirect
8990
github.com/rogpeppe/go-internal v1.14.1 // indirect
91+
github.com/russross/blackfriday/v2 v2.1.0 // indirect
9092
github.com/sagikazarmark/locafero v0.11.0 // indirect
9193
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
9294
github.com/shoenig/go-m1cpu v0.1.6 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
109109
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
110110
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
111111
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
112+
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
112113
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
113114
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
114115
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
@@ -414,6 +415,7 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
414415
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
415416
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
416417
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
418+
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
417419
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
418420
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
419421
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=

internal/cmd/root.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ func newRootCommand() *cobra.Command {
122122

123123
var rootCommand = newRootCommand()
124124

125+
// GetRootCommand returns the root command for documentation generation.
126+
func GetRootCommand() *cobra.Command {
127+
return rootCommand
128+
}
129+
125130
// InitCli adds all child commands to the root command.
126131
func InitCli() {
127132
rootCommand.AddCommand(

internal/platform/cmd/scan_options.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,13 @@ func ComputeFlags(cmd *cobra.Command, options *CliOptions) error {
170170
&options.GenerateCodeClimateReport,
171171
"code-climate",
172172
qdenv.IsGitLab(),
173-
"Generate a code Climate report in SARIF format (compatible with GitLab code Quality), will be saved to the results directory (default true if Qodana is executed on GitLab CI)",
173+
"Generate a Code Climate report in SARIF format (compatible with GitLab code Quality), will be saved to the results directory (default true if Qodana is executed on GitLab CI)",
174174
)
175175
flags.BoolVar(
176176
&options.SendBitBucketInsights,
177177
"bitbucket-insights",
178178
qdenv.IsBitBucket(),
179-
"Send the results BitBucket code Insights, no additional configuration required if ran in BitBucket Pipelines (default true if Qodana is executed on BitBucket Pipelines)",
179+
"Send the results BitBucket Code Insights, no additional configuration required if ran in BitBucket Pipelines (default true if Qodana is executed on BitBucket Pipelines)",
180180
)
181181
flags.BoolVar(&options.ClearCache, "clear-cache", false, "Clear the local Qodana cache before running the analysis")
182182
flags.BoolVarP(&options.ShowReport, "show-report", "w", false, "Serve HTML report on port")
@@ -312,7 +312,7 @@ func ComputeFlags(cmd *cobra.Command, options *CliOptions) error {
312312
&options.NoStatistics,
313313
"no-statistics",
314314
false,
315-
"[qodana-clang/qodana-dotner]Disable sending anonymous statistics",
315+
"[qodana-clang/qodana-dotnet] Disable sending anonymous statistics",
316316
)
317317
flags.StringVar(
318318
&options.ClangCompileCommands,

internal/platform/ext_bitbucket.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ var (
6767
}
6868
)
6969

70-
// sendBitBucketReport sends annotations to BitBucket code Insights
70+
// sendBitBucketReport sends annotations to BitBucket Code Insights
7171
func sendBitBucketReport(annotations []bbapi.ReportAnnotation, toolName, cloudUrl, reportId string) error {
7272
client, ctx := getBitBucketClient(), getBitBucketContext()
7373
repoOwner, repoName, sha := qdenv.GetBitBucketRepoOwner(), qdenv.GetBitBucketRepoName(), qdenv.GetBitBucketCommit()
@@ -123,7 +123,7 @@ func getBitBucketContext() context.Context {
123123
return ctx
124124
}
125125

126-
// buildReport builds a report to be sent to BitBucket code Insights
126+
// buildReport builds a report to be sent to BitBucket Code Insights
127127
func buildReport(toolName string, annotations []bbapi.ReportAnnotation, cloudUrl string) bbapi.Report {
128128
var result string
129129
if len(annotations) == 0 {
@@ -143,7 +143,7 @@ func buildReport(toolName string, annotations []bbapi.ReportAnnotation, cloudUrl
143143
return *data
144144
}
145145

146-
// buildAnnotation builds an annotation to be sent to BitBucket code Insights
146+
// buildAnnotation builds an annotation to be sent to BitBucket Code Insights
147147
func buildAnnotation(r *sarif.Result, ruleDescription string, reportLink string) bbapi.ReportAnnotation {
148148
bbSeverity, ok := toBitBucketSeverity[getSeverity(r)]
149149
if !ok {

internal/platform/ext_gitlab.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func extractLocationProperties(r *sarif.Result) *LocationProperties {
9292
}
9393
}
9494

95-
// sarifResultToCodeClimate converts a SARIF result to a code Climate issue.
95+
// sarifResultToCodeClimate converts a SARIF result to a Code Climate issue.
9696
func sarifResultToCodeClimate(r *sarif.Result) CCIssue {
9797
loc := Location{
9898
Path: "",

scripts/generate-docs.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//go:build ignore
2+
// +build ignore
3+
4+
/*
5+
* Copyright 2021-2024 JetBrains s.r.o.
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* https://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*/
19+
20+
// Script to generate CLI documentation in README.md using cobra/doc.
21+
// Documents init and scan first, then all other non-hidden commands.
22+
package main
23+
24+
import (
25+
"bytes"
26+
"os"
27+
"regexp"
28+
"strings"
29+
30+
"github.com/JetBrains/qodana-cli/internal/cmd"
31+
"github.com/spf13/cobra"
32+
"github.com/spf13/cobra/doc"
33+
)
34+
35+
func main() {
36+
cmd.InitCli()
37+
root := cmd.GetRootCommand()
38+
39+
cmdMap := make(map[string]*cobra.Command)
40+
for _, c := range root.Commands() {
41+
cmdMap[c.Name()] = c
42+
}
43+
44+
var docs bytes.Buffer
45+
writeDoc := func(c *cobra.Command) {
46+
doc.GenMarkdownCustom(c, &docs, func(string) string { return "" })
47+
docs.WriteString("\n")
48+
}
49+
50+
if c := cmdMap["init"]; c != nil && !c.Hidden {
51+
writeDoc(c)
52+
}
53+
if c := cmdMap["scan"]; c != nil && !c.Hidden {
54+
writeDoc(c)
55+
}
56+
for _, c := range root.Commands() {
57+
if !c.Hidden && c.Name() != "init" && c.Name() != "scan" {
58+
writeDoc(c)
59+
}
60+
}
61+
62+
result := cleanup(docs.String())
63+
content, _ := os.ReadFile("README.md")
64+
newContent := regexp.MustCompile(`(?s)## qodana init\n.*?(## Why)`).ReplaceAllString(string(content), result+"$1")
65+
66+
if len(os.Args) > 1 && os.Args[1] == "--check" {
67+
if string(content) != newContent {
68+
println("README.md is out of date. Run 'go run scripts/generate-docs.go' to update it.")
69+
os.Exit(1)
70+
}
71+
println("README.md is up to date.")
72+
return
73+
}
74+
75+
os.WriteFile("README.md", []byte(newContent), 0644)
76+
println("README.md updated.")
77+
}
78+
79+
// cleanup removes ANSI codes, UUID defaults, and replaces home dir with ~
80+
func cleanup(s string) string {
81+
s = regexp.MustCompile(`\x1b\[[0-9;]*m`).ReplaceAllString(s, "")
82+
s = regexp.MustCompile(` \(default "[0-9a-f-]{36}"\)`).ReplaceAllString(s, "")
83+
if h, _ := os.UserHomeDir(); h != "" {
84+
s = strings.ReplaceAll(s, h, "~")
85+
}
86+
return s
87+
}

0 commit comments

Comments
 (0)