Skip to content

Commit 1c48e9c

Browse files
Standardize host flags, move completions to subcommand
- Rename --hostname to --host in login, keep --hostname as deprecated alias - Rename --deepsource-host-endpoint to --host in report, keep old flag as deprecated - Resolve host from config when --host flag is not explicitly set - Replace --install-completions global flag with `completion` subcommand - Simplify README to focus on what the CLI does - Auto-run shell completion setup in install script
1 parent 5c2e0b0 commit 1c48e9c

11 files changed

Lines changed: 290 additions & 113 deletions

File tree

README.md

Lines changed: 13 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,24 @@
1-
<p align="center">
2-
<img src="https://cms.deepsource.io/logo-wordmark-dark.svg" />
3-
</p>
1+
# DeepSource Command Line Interface
42

5-
<p align="center">
6-
<a href="https://docs.deepsource.com">Docs</a> |
7-
<a href="https://deepsource.com">Get Started</a> |
8-
<a href="https://discuss.deepsource.com/">Discuss</a>
9-
</p>
3+
Access DeepSource analysis data directly from your terminal.
104

11-
<p align="center">
12-
The Code Health Platform
13-
</p>
5+
DeepSource CLI lets you view issues, metrics, vulnerabilities, and analysis runs from your terminal.
146

15-
</p>
7+
## What you can do
168

17-
---
9+
- View the status and results of analysis runs across your repositories
10+
- Filter and inspect code issues by severity, category, analyzer, or file path
11+
- Check code coverage, code health scores, and other metrics
12+
- Send test coverage artifacts to DeepSource from CI pipelines or local environments
13+
- Review dependency vulnerabilities detected in your codebase
14+
- Get a report card of code health across all analyzers
1815

19-
# CLI
20-
21-
Command line interface to DeepSource
22-
23-
## Installation
24-
25-
### macOS
26-
27-
DeepSource CLI is available on macOS via [Homebrew](https://brew.sh/):
28-
29-
```sh
30-
brew install deepsourcelabs/cli/deepsource
31-
```
32-
### Binary Installation
33-
34-
```sh
35-
curl https://cli.deepsource.com/install | sh
36-
```
37-
This script will detect the operating system and architecture and puts deepsource binary in `./bin/deepsource`.
38-
39-
## Configuring DSN
40-
41-
In order to report test-coverage to DeepSource using the `report` command, an environment variable named as `DEEPSOURCE_DSN` has to
42-
be set. It's value will be available under 'Settings' tab of the repository page.
43-
44-
## Authentication
45-
46-
### Browser-based login (default)
47-
```sh
48-
deepsource auth login
49-
```
50-
51-
### Token-based login
52-
```sh
53-
deepsource auth login --token <your-token>
54-
```
55-
56-
### Enterprise (custom hostname)
57-
```sh
58-
deepsource auth login --host your-enterprise.deepsource.com
59-
```
60-
61-
### OIDC-based reporting (CI environments)
62-
```sh
63-
deepsource report --analyzer test-coverage --key go --value-file ./coverage.out --use-oidc
64-
```
65-
66-
## Usage
67-
68-
The CLI provides access to a wide range of commands. Here is a list of the
69-
commands along with their brief description.
70-
71-
```
72-
Usage:
73-
deepsource <command> [flags]
74-
75-
Available commands are:
76-
auth Authentication commands (login, logout, refresh, status)
77-
runs View analysis runs
78-
issues View issues in a repository
79-
repo Operations related to the project repository (status, view)
80-
report Report artifacts to DeepSource
81-
metrics View repository metrics
82-
vulnerabilities View vulnerabilities in a repository
83-
84-
Help:
85-
Use 'deepsource <command> --help/-h' for more information about the command.
86-
```
16+
All commands support JSON output for scripting and automation.
8717

8818
## Documentation
8919

90-
For complete documentation, refer to the [CLI Documentation](https://docs.deepsource.com/docs/cli)
91-
92-
## Feedback/Support
93-
94-
Want to share any feedback or need any help regarding the CLI? Feel free to
95-
open a discussion in the [community forum](https://discuss.deepsource.com)
20+
- [Installation](https://docs.deepsource.com/docs/cli#installation)
21+
- [Usage](https://docs.deepsource.com/docs/cli)
9622

9723
## License
9824

command/auth/login/login.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func NewCmdLoginWithDeps(deps *cmddeps.Deps) *cobra.Command {
4646
4747
Use %[3]s to authenticate with a specific DeepSource instance, for example:
4848
%[4]s
49-
`, style.Yellow("--with-token"), style.Cyan("deepsource auth login --with-token dsp_abcd"), style.Yellow("--hostname"), style.Cyan("deepsource auth login --hostname my_instance"))
49+
`, style.Yellow("--with-token"), style.Cyan("deepsource auth login --with-token dsp_abcd"), style.Yellow("--host"), style.Cyan("deepsource auth login --host my_instance"))
5050

5151
opts := LoginOptions{
5252
AuthTimedOut: false,
@@ -66,8 +66,10 @@ func NewCmdLoginWithDeps(deps *cmddeps.Deps) *cobra.Command {
6666
},
6767
}
6868

69-
// --host, -h flag
69+
// --host flag (--hostname kept as deprecated alias)
70+
cmd.Flags().StringVar(&opts.HostName, "host", "", "Authenticate with a specific DeepSource instance")
7071
cmd.Flags().StringVar(&opts.HostName, "hostname", "", "Authenticate with a specific DeepSource instance")
72+
_ = cmd.Flags().MarkDeprecated("hostname", "use --host instead")
7173
cmd.Flags().BoolVarP(&opts.Interactive, "interactive", "i", false, "Interactive login prompt for authenticating with DeepSource")
7274
cmd.Flags().StringVar(&opts.PAT, "with-token", "", "Personal Access Token (PAT) for DeepSource")
7375

command/auth/login/tests/login_test.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ func TestLoginPATFlow(t *testing.T) {
3636
}
3737
}
3838

39-
func TestLoginPATWithHostname(t *testing.T) {
39+
func TestLoginPATWithHost(t *testing.T) {
4040
cfgMgr := testutil.CreateExpiredTestConfigManager(t, "", "deepsource.com", "")
4141

4242
deps := &cmddeps.Deps{
4343
ConfigMgr: cfgMgr,
4444
}
4545

4646
cmd := loginCmd.NewCmdLoginWithDeps(deps)
47-
cmd.SetArgs([]string{"--with-token", "dsp_xyz789", "--hostname", "enterprise.example.com"})
47+
cmd.SetArgs([]string{"--with-token", "dsp_xyz789", "--host", "enterprise.example.com"})
4848

4949
if err := cmd.Execute(); err != nil {
5050
t.Fatalf("unexpected error: %v", err)
@@ -62,6 +62,33 @@ func TestLoginPATWithHostname(t *testing.T) {
6262
}
6363
}
6464

65+
func TestLoginPATWithHostnameDeprecated(t *testing.T) {
66+
// --hostname still works as a deprecated alias
67+
cfgMgr := testutil.CreateExpiredTestConfigManager(t, "", "deepsource.com", "")
68+
69+
deps := &cmddeps.Deps{
70+
ConfigMgr: cfgMgr,
71+
}
72+
73+
cmd := loginCmd.NewCmdLoginWithDeps(deps)
74+
cmd.SetArgs([]string{"--with-token", "dsp_compat", "--hostname", "legacy.example.com"})
75+
76+
if err := cmd.Execute(); err != nil {
77+
t.Fatalf("unexpected error: %v", err)
78+
}
79+
80+
cfg, err := cfgMgr.Load()
81+
if err != nil {
82+
t.Fatalf("failed to load config: %v", err)
83+
}
84+
if cfg.Token != "dsp_compat" {
85+
t.Errorf("expected token %q, got %q", "dsp_compat", cfg.Token)
86+
}
87+
if cfg.Host != "legacy.example.com" {
88+
t.Errorf("expected host %q, got %q", "legacy.example.com", cfg.Host)
89+
}
90+
}
91+
6592
func TestLoginDefaultHostname(t *testing.T) {
6693
cfgMgr := testutil.CreateExpiredTestConfigManager(t, "", "deepsource.com", "")
6794

@@ -80,7 +107,7 @@ func TestLoginDefaultHostname(t *testing.T) {
80107
if err != nil {
81108
t.Fatalf("failed to load config: %v", err)
82109
}
83-
// Without --hostname, host defaults to deepsource.com
110+
// Without --host, host defaults to deepsource.com
84111
if cfg.Host != "deepsource.com" {
85112
t.Errorf("expected host %q, got %q", "deepsource.com", cfg.Host)
86113
}

command/completion/completion.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package completion
2+
3+
import (
4+
"os"
5+
6+
"github.com/deepsourcelabs/cli/internal/cli/completion"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
func NewCmdCompletion() *cobra.Command {
11+
return &cobra.Command{
12+
Use: "completion",
13+
Short: "Install shell completions for bash, zsh, or fish",
14+
RunE: func(cmd *cobra.Command, args []string) error {
15+
return completion.Install(cmd.Root(), os.Stderr)
16+
},
17+
}
18+
}

command/report/host_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package report
2+
3+
import "testing"
4+
5+
func TestHostToEndpoint(t *testing.T) {
6+
tests := []struct {
7+
host string
8+
want string
9+
}{
10+
{"deepsource.com", "https://app.deepsource.com"},
11+
{"deepsource.io", "https://app.deepsource.com"},
12+
{"deepsource.one", "https://app.deepsource.one"},
13+
{"enterprise.example.com", "https://enterprise.example.com"},
14+
}
15+
for _, tt := range tests {
16+
t.Run(tt.host, func(t *testing.T) {
17+
if got := hostToEndpoint(tt.host); got != tt.want {
18+
t.Errorf("hostToEndpoint(%q) = %q, want %q", tt.host, got, tt.want)
19+
}
20+
})
21+
}
22+
}

command/report/report.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@ func NewCmdReportWithDeps(deps *container.Container) *cobra.Command {
6969
if deps == nil {
7070
deps = container.New()
7171
}
72+
73+
// Resolve host: explicit flag > config > default
74+
if !cmd.Flags().Changed("host") && !cmd.Flags().Changed("deepsource-host-endpoint") {
75+
if cfg, err := deps.Config.Load(); err == nil && cfg.Host != "" {
76+
opts.DeepSourceHostEndpoint = hostToEndpoint(cfg.Host)
77+
}
78+
}
79+
if opts.DeepSourceHostEndpoint == "" {
80+
opts.DeepSourceHostEndpoint = "https://app.deepsource.com"
81+
}
82+
7283
svc := reportsvc.NewService(reportsvc.ServiceDeps{
7384
GitClient: deps.GitClient,
7485
HTTPClient: deps.HTTPClient,
@@ -99,7 +110,9 @@ func NewCmdReportWithDeps(deps *container.Container) *cobra.Command {
99110
cmd.Flags().StringVar(&opts.OIDCRequestToken, "oidc-request-token", "", "request ID token to fetch an OIDC token from OIDC provider")
100111

101112
cmd.Flags().StringVar(&opts.OIDCRequestUrl, "oidc-request-url", "", "OIDC provider's request URL to fetch an OIDC token")
102-
cmd.Flags().StringVar(&opts.DeepSourceHostEndpoint, "deepsource-host-endpoint", "https://app.deepsource.com", "DeepSource host endpoint where the app is running. Defaults to the cloud endpoint https://app.deepsource.com")
113+
cmd.Flags().StringVar(&opts.DeepSourceHostEndpoint, "host", "", "DeepSource host endpoint")
114+
cmd.Flags().StringVar(&opts.DeepSourceHostEndpoint, "deepsource-host-endpoint", "", "DeepSource host endpoint")
115+
_ = cmd.Flags().MarkDeprecated("deepsource-host-endpoint", "use --host instead")
103116
cmd.Flags().StringVar(&opts.OIDCProvider, "oidc-provider", "", "OIDC provider to use for authentication. Supported providers: github-actions")
104117
cmd.Flags().StringVar(&opts.Output, "output", "pretty", "Output format: pretty, json")
105118

@@ -170,7 +183,7 @@ func setReportUsageFunc(cmd *cobra.Command) {
170183
flags []string
171184
}{
172185
{"Artifact", []string{"analyzer", "analyzer-type", "key", "value", "value-file"}},
173-
{"Authentication", []string{"use-oidc", "oidc-provider", "oidc-request-token", "oidc-request-url", "deepsource-host-endpoint"}},
186+
{"Authentication", []string{"use-oidc", "oidc-provider", "oidc-request-token", "oidc-request-url", "host"}},
174187
{"Output", []string{"output"}},
175188
{"General", []string{"skip-verify", "help"}},
176189
}
@@ -223,6 +236,18 @@ func flagUsageLine(f *pflag.Flag) string {
223236
return line
224237
}
225238

239+
// hostToEndpoint converts a bare config hostname to a full endpoint URL.
240+
func hostToEndpoint(host string) string {
241+
switch host {
242+
case "deepsource.com", "deepsource.io":
243+
return "https://app.deepsource.com"
244+
case "deepsource.one":
245+
return "https://app.deepsource.one"
246+
default:
247+
return "https://" + host
248+
}
249+
}
250+
226251
func printReportResult(output interfaces.OutputWriter, format string, result *reportsvc.Result) error {
227252
write := func(format string, args ...interface{}) {
228253
if output == nil {

0 commit comments

Comments
 (0)