Files
member-console/cmd/lint.go
T
cgalo5758 88db730fcc Add dual licensing and SPDX headers
Introduce a commercial license option alongside AGPL-3.0-only, require a
CLA for contributors, and document the terms in COMMERCIAL.md and
NOTICE. Add a script to stamp SPDX headers on Go files and apply it
across the tree.
2026-09-06 02:29:42 -05:00

68 lines
2.7 KiB
Go

// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"git.coopcloud.tech/wiki-cafe/member-console/internal/lint"
)
var lintCmd = &cobra.Command{
Use: "lint",
Short: "Static checks for operator UI integrity (M7f.1)",
Long: `lint walks the Go source under internal/server/ and the templates
under internal/embeds/templates/ and reports:
- dead routes: routeURL patterns with no registered handler
- dead swap targets: hx-target="#X" with no matching id="X"
- stale tab references: ?tab= was retired in M7d (operator-mpa-conversion)
- banned literal URLs: interpolated hx-* URL strings must use routeURL
Exits 0 on a clean tree, 1 on violations, 2 on internal errors. Safe to wire
into CI or a pre-commit hook. See status/milestones.md (M7f.1) and
docs/operator-ux-conventions.md §9.`,
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
serverDir, _ := cmd.Flags().GetString("server-dir")
templateDir, _ := cmd.Flags().GetString("template-dir")
walkthroughDir, _ := cmd.Flags().GetString("walkthrough-dir")
allowlistPath, _ := cmd.Flags().GetString("anatomy-allowlist")
manifestPath, _ := cmd.Flags().GetString("screens-manifest")
res, err := lint.Run(lint.Config{
ServerDir: serverDir,
TemplateDir: templateDir,
WalkthroughDir: walkthroughDir,
AllowlistPath: allowlistPath,
ManifestPath: manifestPath,
})
if err != nil {
fmt.Fprintf(os.Stderr, "lint: %v\n", err)
os.Exit(2)
}
for _, v := range res.Violations {
fmt.Fprintf(os.Stderr, "%s:%d: [%s] %s\n", v.File, v.Line, v.Rule, v.Message)
}
if len(res.Violations) > 0 {
fmt.Fprintf(os.Stderr, "\nlint: %d violation(s) across %d routes / %d URL refs\n",
len(res.Violations), res.RoutesScanned, res.URLRefsScanned)
os.Exit(1)
}
fmt.Fprintf(os.Stderr, "lint: ok (%d routes, %d URL refs; %d anatomy violation(s) allowlisted)\n", res.RoutesScanned, res.URLRefsScanned, res.Allowlisted)
},
}
func init() {
lintCmd.Flags().String("server-dir", "internal/server", "Go source directory containing mux.HandleFunc registrations")
lintCmd.Flags().String("template-dir", "internal/embeds/templates", "Embedded templates directory")
lintCmd.Flags().String("anatomy-allowlist", "internal/lint/anatomy_allowlist.txt", `Templates not yet rebuilt on the page-anatomy parts ("-" disables the anatomy rules)`)
lintCmd.Flags().String("screens-manifest", "test/e2e/screens/manifest.go", `Screens manifest for the screen-coverage rule ("-" disables it)`)
lintCmd.Flags().String("walkthrough-dir", "test/e2e/operator-walkthroughs", `Walkthrough directory for coverage rule (set "-" to disable)`)
rootCmd.AddCommand(lintCmd)
}