mirror of
https://github.com/LukeHagar/slinky.git
synced 2025-12-06 04:21:20 +00:00
Refactor entrypoint.sh, check.go, and run.go to support positional targets for URL scanning, enhancing flexibility. Update README.md to reflect changes in target handling and provide clearer usage instructions.
This commit is contained in:
16
README.md
16
README.md
@@ -51,14 +51,18 @@ go build -o slinky ./
|
||||
Usage:
|
||||
|
||||
```bash
|
||||
slinky check . --patterns "docs/**/*.md" --patterns "**/*.go" --md-out results.md --json-out results.json
|
||||
# Headless: provide one or more targets (files, dirs, or globs)
|
||||
slinky check **/*
|
||||
slinky check ./docs/**/* ./markdown/**/*
|
||||
|
||||
# TUI mode: same targets
|
||||
slinky run **/*
|
||||
```
|
||||
|
||||
TUI mode:
|
||||
|
||||
```bash
|
||||
slinky run . --patterns "**/*"
|
||||
```
|
||||
Notes:
|
||||
- Targets can be files, directories, or doublestar globs. Multiple targets are allowed.
|
||||
- If no targets are provided, the default is `**/*` relative to the current working directory.
|
||||
- Legacy flags `--glob` and `--patterns` are still supported, but positional targets are preferred.
|
||||
|
||||
### Notes
|
||||
|
||||
|
||||
68
cmd/check.go
68
cmd/check.go
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -29,24 +30,31 @@ type SerializableResult struct {
|
||||
|
||||
func init() {
|
||||
checkCmd := &cobra.Command{
|
||||
Use: "check [path]",
|
||||
Short: "Scan a directory for URLs and validate them (headless)",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Use: "check [targets...]",
|
||||
Short: "Scan for URLs and validate them (headless)",
|
||||
Args: cobra.ArbitraryArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
path := "."
|
||||
if len(args) == 1 {
|
||||
path = args[0]
|
||||
}
|
||||
|
||||
var gl []string
|
||||
if len(patterns) > 0 {
|
||||
gl = append(gl, patterns...)
|
||||
} else if globPat != "" {
|
||||
gl = strings.Split(globPat, ",")
|
||||
if len(args) > 0 {
|
||||
for _, a := range args {
|
||||
for _, part := range strings.Split(a, ",") {
|
||||
p := strings.TrimSpace(part)
|
||||
if p != "" {
|
||||
gl = append(gl, toSlash(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gl = []string{"**/*"}
|
||||
}
|
||||
|
||||
gl = expandDirectories(path, gl)
|
||||
|
||||
// Emit normalized patterns for debugging
|
||||
fmt.Printf("::debug:: Effective patterns: %s\n", strings.Join(gl, ","))
|
||||
|
||||
timeout := time.Duration(timeoutSeconds) * time.Second
|
||||
cfg := web.Config{MaxConcurrency: maxConcurrency, RequestTimeout: timeout}
|
||||
|
||||
@@ -149,8 +157,6 @@ func init() {
|
||||
},
|
||||
}
|
||||
|
||||
checkCmd.Flags().StringVar(&globPat, "glob", "", "comma-separated glob patterns for files (doublestar); empty = all files")
|
||||
checkCmd.Flags().StringSliceVar(&patterns, "patterns", nil, "file match patterns (doublestar). Examples: docs/**/*.md,**/*.go; defaults to **/*")
|
||||
checkCmd.Flags().IntVar(&maxConcurrency, "concurrency", 16, "maximum concurrent requests")
|
||||
checkCmd.Flags().StringVar(&jsonOut, "json-out", "", "path to write full JSON results (array)")
|
||||
checkCmd.Flags().StringVar(&mdOut, "md-out", "", "path to write Markdown report for PR comment")
|
||||
@@ -165,7 +171,43 @@ func init() {
|
||||
var (
|
||||
timeoutSeconds int
|
||||
failOnFailures bool
|
||||
patterns []string
|
||||
repoBlobBase string
|
||||
respectGitignore bool
|
||||
)
|
||||
|
||||
func toSlash(p string) string {
|
||||
p = strings.TrimSpace(p)
|
||||
if p == "" {
|
||||
return p
|
||||
}
|
||||
p = filepath.ToSlash(p)
|
||||
if after, ok := strings.CutPrefix(p, "./"); ok {
|
||||
p = after
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func hasGlobMeta(s string) bool {
|
||||
return strings.ContainsAny(s, "*?[")
|
||||
}
|
||||
|
||||
func expandDirectories(root string, pats []string) []string {
|
||||
var out []string
|
||||
for _, p := range pats {
|
||||
pp := strings.TrimSpace(p)
|
||||
if pp == "" {
|
||||
continue
|
||||
}
|
||||
if hasGlobMeta(pp) {
|
||||
out = append(out, pp)
|
||||
continue
|
||||
}
|
||||
abs := filepath.Join(root, filepath.FromSlash(pp))
|
||||
if fi, err := os.Stat(abs); err == nil && fi.IsDir() {
|
||||
out = append(out, strings.TrimSuffix(pp, "/")+"/**/*")
|
||||
} else {
|
||||
out = append(out, pp)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
26
cmd/run.go
26
cmd/run.go
@@ -11,29 +11,28 @@ import (
|
||||
|
||||
func init() {
|
||||
runCmd := &cobra.Command{
|
||||
Use: "run [path]",
|
||||
Use: "run [targets...]",
|
||||
Short: "Scan a directory/repo for URLs in files and validate them (TUI)",
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
Args: cobra.ArbitraryArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
path := "."
|
||||
if len(args) == 1 {
|
||||
path = args[0]
|
||||
}
|
||||
cfg := web.Config{MaxConcurrency: maxConcurrency}
|
||||
var gl []string
|
||||
if len(patterns) > 0 {
|
||||
gl = append(gl, patterns...)
|
||||
} else if globPat != "" {
|
||||
gl = strings.Split(globPat, ",")
|
||||
if len(args) > 0 {
|
||||
for _, a := range args {
|
||||
for _, part := range strings.Split(a, ",") {
|
||||
p := strings.TrimSpace(part)
|
||||
if p != "" {
|
||||
gl = append(gl, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gl = []string{"**/*"}
|
||||
}
|
||||
return tui.Run(path, gl, cfg, jsonOut, mdOut)
|
||||
return tui.Run(".", gl, cfg, jsonOut, mdOut)
|
||||
},
|
||||
}
|
||||
|
||||
runCmd.Flags().StringVar(&globPat, "glob", "", "comma-separated glob patterns for files (doublestar); empty = all files")
|
||||
runCmd.Flags().StringSliceVar(&patterns, "patterns", nil, "file match patterns (doublestar). Examples: docs/**/*.md,**/*.go; defaults to **/*")
|
||||
runCmd.Flags().IntVar(&maxConcurrency, "concurrency", 16, "maximum concurrent requests")
|
||||
runCmd.Flags().StringVar(&jsonOut, "json-out", "", "path to write full JSON results (array)")
|
||||
runCmd.Flags().StringVar(&mdOut, "md-out", "", "path to write Markdown report for PR comment")
|
||||
@@ -44,6 +43,5 @@ func init() {
|
||||
var (
|
||||
maxConcurrency int
|
||||
jsonOut string
|
||||
globPat string
|
||||
mdOut string
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ COMMENT_PR_ARG="${INPUT_COMMENT_PR:-true}"
|
||||
STEP_SUMMARY_ARG="${INPUT_STEP_SUMMARY:-true}"
|
||||
|
||||
# Build argv safely
|
||||
set -- check "$PATH_ARG" --concurrency "$CONCURRENCY_ARG" --timeout "$TIMEOUT_ARG"
|
||||
set -- check --concurrency "$CONCURRENCY_ARG" --timeout "$TIMEOUT_ARG"
|
||||
if [ "${FAIL_ON_FAILURES_ARG}" = "true" ]; then
|
||||
set -- "$@" --fail-on-failures=true
|
||||
else
|
||||
@@ -22,12 +22,9 @@ else
|
||||
fi
|
||||
|
||||
if [ -n "${PATTERNS_ARG}" ]; then
|
||||
NORM_PATTERNS=$(printf "%s" "${PATTERNS_ARG}" | sed 's/,[[:space:]]*/,/g')
|
||||
IFS=','
|
||||
for pat in $NORM_PATTERNS; do
|
||||
set -- "$@" --patterns "$pat"
|
||||
done
|
||||
unset IFS
|
||||
set -- "$@" "$PATTERNS_ARG"
|
||||
else
|
||||
set -- "$@" "**/*"
|
||||
fi
|
||||
|
||||
if [ -n "${JSON_OUT_ARG}" ]; then
|
||||
@@ -60,8 +57,9 @@ fi
|
||||
|
||||
# Emit consolidated config at start (visible with ACTIONS_STEP_DEBUG=true)
|
||||
EFFECTIVE_REPO_BLOB_BASE="${SLINKY_REPO_BLOB_BASE_URL:-$REPO_BLOB_BASE_ARG}"
|
||||
printf "::debug:: Config: path=%s patterns=%s concurrency=%s timeout=%s respect_gitignore=%s json_out=%s md_out=%s fail_on_failures=%s comment_pr=%s step_summary=%s repo_blob_base_url=%s\n" \
|
||||
"$PATH_ARG" "$PATTERNS_ARG" "$CONCURRENCY_ARG" "$TIMEOUT_ARG" "$RESPECT_GITIGNORE_ARG" "$JSON_OUT_ARG" "$MD_OUT_ARG" \
|
||||
TARGETS_DEBUG="${PATTERNS_ARG:-**/*}"
|
||||
printf "::debug:: Config: targets=%s concurrency=%s timeout=%s respect_gitignore=%s json_out=%s md_out=%s fail_on_failures=%s comment_pr=%s step_summary=%s repo_blob_base_url=%s\n" \
|
||||
"$TARGETS_DEBUG" "$CONCURRENCY_ARG" "$TIMEOUT_ARG" "$RESPECT_GITIGNORE_ARG" "$JSON_OUT_ARG" "$MD_OUT_ARG" \
|
||||
"$FAIL_ON_FAILURES_ARG" "$COMMENT_PR_ARG" "$STEP_SUMMARY_ARG" "$EFFECTIVE_REPO_BLOB_BASE"
|
||||
printf "::debug:: CLI Args: slinky %s\n" "$*"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user