Skip to content

Commit 054f270

Browse files
committed
Updated code on reviews and feedback
1 parent 7fc0a96 commit 054f270

File tree

13 files changed

+559
-225
lines changed

13 files changed

+559
-225
lines changed

IDE_SETUP_COMMANDS.md

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,47 @@ The IDE setup commands allow developers to configure their development environme
1111
- Maintain control over which extensions/plugins are available
1212
- Work in air-gapped or restricted network environments
1313

14+
## Prerequisites
15+
16+
Before using the IDE setup commands, ensure you have the JFrog CLI installed:
17+
18+
```bash
19+
# Install JFrog CLI (macOS/Linux)
20+
curl -fL https://getcli.jfrog.io | sh && mv jfrog /usr/local/bin/
21+
22+
# Or with Homebrew (macOS/Linux)
23+
brew install jfrog-cli
24+
25+
# Or with Chocolatey (Windows)
26+
choco install jfrog-cli
27+
```
28+
29+
For more details and installation options, see the [JFrog CLI documentation](https://jfrog.com/getcli/).
30+
31+
## How File Modifications Are Performed
32+
33+
The IDE setup commands update configuration files directly on your system. The following tools and methods are used in the background:
34+
35+
- **macOS/Linux:** Uses the `sed` command-line tool to modify JSON or properties files in-place.
36+
- **Windows:** Uses PowerShell scripts to update configuration files.
37+
- **Backup:** Before any modification, a backup of the original file is created in the same or a dedicated backup directory.
38+
39+
> **Note:** You must have the required permissions to modify these files. For system-wide installations, you may need to run the command with `sudo` (macOS/Linux) or as Administrator (Windows).
40+
1441
## Commands
1542

16-
### VSCode Configuration: `jf rt vscode-config`
43+
### VSCode Configuration: `jf vscode-config`
1744

1845
Configures Visual Studio Code to use JFrog Artifactory for extensions.
1946

2047
#### Syntax
2148
```bash
22-
jf rt vscode-config <service-url> [flags]
49+
jf vscode-config <service-url> [flags]
2350
```
2451

2552
#### Aliases
26-
- `jf rt vscode`
53+
- `jf vscode`
54+
- `jf code`
2755

2856
#### Parameters
2957

@@ -47,22 +75,22 @@ https://<artifactory-url>/artifactory/api/vscodeextensions/<repo-key>/_apis/publ
4775

4876
**Basic usage (no server authentication):**
4977
```bash
50-
jf rt vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery
78+
jf vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery
5179
```
5280

5381
**With custom product.json path:**
5482
```bash
55-
jf rt vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery --product-json-path="/custom/path/product.json"
83+
jf vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery --product-json-path="/custom/path/product.json"
5684
```
5785

5886
**With repository validation:**
5987
```bash
60-
jf rt vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery --url https://mycompany.jfrog.io --access-token mytoken123
88+
jf vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery --url https://mycompany.jfrog.io --access-token mytoken123
6189
```
6290

6391
**Using pre-configured server:**
6492
```bash
65-
jf rt vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery --server-id my-artifactory
93+
jf vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery --server-id my-artifactory
6694
```
6795

6896
#### Behavior
@@ -88,17 +116,18 @@ jf rt vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/
88116
- `/opt/visual-studio-code/resources/app/product.json`
89117
- `~/.local/share/applications/code/resources/app/product.json`
90118

91-
### JetBrains Configuration: `jf rt jetbrains-config`
119+
### JetBrains Configuration: `jf jetbrains-config`
92120

93121
Configures JetBrains IDEs to use JFrog Artifactory for plugins.
94122

95123
#### Syntax
96124
```bash
97-
jf rt jetbrains-config <repository-url> [flags]
125+
jf jetbrains-config <repository-url> [flags]
98126
```
99127

100128
#### Aliases
101-
- `jf rt jetbrains`
129+
- `jf jetbrains`
130+
- `jf jb`
102131

103132
#### Parameters
104133

@@ -121,17 +150,17 @@ https://<artifactory-url>/artifactory/api/jetbrainsplugins/<repo-key>
121150

122151
**Basic usage (no server authentication):**
123152
```bash
124-
jf rt jetbrains-config https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins
153+
jf jetbrains-config https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins
125154
```
126155

127156
**With repository validation:**
128157
```bash
129-
jf rt jetbrains-config https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins --url https://mycompany.jfrog.io --access-token mytoken123
158+
jf jetbrains-config https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins --url https://mycompany.jfrog.io --access-token mytoken123
130159
```
131160

132161
**Using pre-configured server:**
133162
```bash
134-
jf rt jetbrains-config https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins --server-id my-artifactory
163+
jf jetbrains-config https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins --server-id my-artifactory
135164
```
136165

137166
#### Behavior
@@ -252,10 +281,10 @@ The IDE setup commands can be integrated into development environment setup scri
252281
# Developer onboarding script
253282

254283
# Configure VSCode
255-
jf rt vscode-config https://company.jfrog.io/artifactory/api/vscodeextensions/approved-extensions/_apis/public/gallery
284+
jf vscode-config https://company.jfrog.io/artifactory/api/vscodeextensions/approved-extensions/_apis/public/gallery
256285

257286
# Configure JetBrains IDEs
258-
jf rt jetbrains-config https://company.jfrog.io/artifactory/api/jetbrainsplugins/approved-plugins
287+
jf jetbrains-config https://company.jfrog.io/artifactory/api/jetbrainsplugins/approved-plugins
259288

260289
echo "IDE configuration complete. Please restart your IDEs."
261290
```
@@ -297,4 +326,26 @@ echo "IDE configuration complete. Please restart your IDEs."
297326
└── <plugin-id>/
298327
└── <version>/
299328
└── <plugin-name>-<version>.zip
300-
```
329+
```
330+
331+
## Troubleshooting
332+
333+
If you encounter issues during IDE configuration, consider the following:
334+
335+
- **File modification failed:**
336+
- Ensure you have write permissions to the configuration file.
337+
- On macOS/Linux, try running the command with `sudo`.
338+
- On Windows, run your terminal as Administrator.
339+
- Check that `sed` (macOS/Linux) or PowerShell (Windows) is available in your environment.
340+
- **VSCode/JetBrains not detected:**
341+
- Make sure the IDE is installed in a standard location, or specify the path manually using the appropriate flag.
342+
- **Configuration not applied:**
343+
- Verify that a backup file was created (indicates successful file access).
344+
- Manually inspect the configuration file to ensure changes were made.
345+
- Restart your IDE after running the command.
346+
- **Permission errors:**
347+
- See the error message for instructions on how to resolve permission issues.
348+
- **Backup/restore issues:**
349+
- If something goes wrong, restore the original file from the backup created by the CLI.
350+
351+
For more troubleshooting tips, see the [JFrog CLI documentation](https://jfrog.com/getcli/).

artifactory/cli/cli.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import (
66
"strings"
77

88
ioutils "github.com/jfrog/gofrog/io"
9-
"github.com/jfrog/jfrog-cli-artifactory/artifactory/cli/ide/jetbrains"
10-
"github.com/jfrog/jfrog-cli-artifactory/artifactory/cli/ide/vscode"
119
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/buildinfo"
1210
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/container"
1311
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/curl"
@@ -406,10 +404,6 @@ func GetCommands() []components.Command {
406404
Category: replicCategory,
407405
},
408406
}
409-
// Add all VSCode commands
410-
commands = append(commands, vscode.GetCommands()...)
411-
// Add all JetBrains commands
412-
commands = append(commands, jetbrains.GetCommands()...)
413407

414408
return commands
415409
}

artifactory/cli/ide/common.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package ide
2+
3+
import (
4+
"fmt"
5+
6+
pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"
7+
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
8+
)
9+
10+
// ValidateSingleNonEmptyArg checks that there is exactly one argument and it is not empty.
11+
func ValidateSingleNonEmptyArg(c *components.Context, usage string) (string, error) {
12+
if c.GetNumberOfArgs() != 1 {
13+
return "", pluginsCommon.WrongNumberOfArgumentsHandler(c)
14+
}
15+
arg := c.GetArgumentAt(0)
16+
if arg == "" {
17+
return "", fmt.Errorf("argument cannot be empty\n\nUsage: %s", usage)
18+
}
19+
return arg, nil
20+
}
21+
22+
// HasServerConfigFlags checks if any server configuration flags are provided
23+
func HasServerConfigFlags(c *components.Context) bool {
24+
return c.IsFlagSet("url") ||
25+
c.IsFlagSet("user") ||
26+
c.IsFlagSet("access-token") ||
27+
c.IsFlagSet("server-id") ||
28+
// Only consider password if other required fields are also provided
29+
(c.IsFlagSet("password") && (c.IsFlagSet("url") || c.IsFlagSet("server-id")))
30+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package ide
2+
3+
const VscodeConfigDescription = `
4+
Configure VSCode to use JFrog Artifactory for extensions.
5+
6+
The service URL should be in the format:
7+
https://<artifactory-url>/artifactory/api/vscodeextensions/<repo-key>/_apis/public/gallery
8+
9+
Examples:
10+
jf vscode-config https://mycompany.jfrog.io/artifactory/api/vscodeextensions/vscode-extensions/_apis/public/gallery
11+
12+
This command will:
13+
- Modify the VSCode product.json file to change the extensions gallery URL
14+
- Create an automatic backup before making changes
15+
- Require VSCode to be restarted to apply changes
16+
17+
Optional: Provide server configuration flags (--url, --user, --password, --access-token, or --server-id)
18+
to enable repository validation. Without these flags, the command will only modify the local VSCode configuration.
19+
20+
Note: On macOS/Linux, you may need to run with sudo for system-installed VSCode.
21+
`
22+
23+
const JetbrainsConfigDescription = `
24+
Configure JetBrains IDEs to use JFrog Artifactory for plugins.
25+
26+
The repository URL should be in the format:
27+
https://<artifactory-url>/artifactory/api/jetbrainsplugins/<repo-key>
28+
29+
Examples:
30+
jf jetbrains-config https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins
31+
32+
This command will:
33+
- Detect all installed JetBrains IDEs
34+
- Modify each IDE's idea.properties file to add the plugins repository URL
35+
- Create automatic backups before making changes
36+
- Require IDEs to be restarted to apply changes
37+
38+
Optional: Provide server configuration flags (--url, --user, --password, --access-token, or --server-id)
39+
to enable repository validation. Without these flags, the command will only modify the local IDE configuration.
40+
41+
Supported IDEs: IntelliJ IDEA, PyCharm, WebStorm, PhpStorm, RubyMine, CLion, DataGrip, GoLand, Rider, Android Studio, AppCode, RustRover, Aqua
42+
`

artifactory/cli/ide/jetbrains/cli.go

Lines changed: 23 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package jetbrains
22

33
import (
44
"fmt"
5+
"net/url"
56
"strings"
67

8+
"github.com/jfrog/jfrog-cli-artifactory/artifactory/cli/ide"
79
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/ide/jetbrains"
810
pluginsCommon "github.com/jfrog/jfrog-cli-core/v2/plugins/common"
911
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
@@ -13,39 +15,18 @@ import (
1315
func GetCommands() []components.Command {
1416
return []components.Command{
1517
{
16-
Name: "jetbrains-config",
17-
Aliases: []string{"jetbrains"},
18-
Action: jetbrainsConfigCmd,
19-
Description: `Configure JetBrains IDEs to use JFrog Artifactory for plugins.
20-
21-
The repository URL should be in the format:
22-
https://<artifactory-url>/artifactory/api/jetbrainsplugins/<repo-key>
23-
24-
Examples:
25-
jf rt jetbrains-config https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins
26-
27-
This command will:
28-
- Detect all installed JetBrains IDEs
29-
- Modify each IDE's idea.properties file to add the plugins repository URL
30-
- Create automatic backups before making changes
31-
- Require IDEs to be restarted to apply changes
32-
33-
Optional: Provide server configuration flags (--url, --user, --password, --access-token, or --server-id)
34-
to enable repository validation. Without these flags, the command will only modify the local IDE configuration.
35-
36-
Supported IDEs: IntelliJ IDEA, PyCharm, WebStorm, PhpStorm, RubyMine, CLion, DataGrip, GoLand, Rider, Android Studio, AppCode, RustRover, Aqua`,
18+
Name: "jetbrains-config",
19+
Aliases: []string{"jetbrains"},
20+
Action: jetbrainsConfigCmd,
21+
Description: ide.JetbrainsConfigDescription,
3722
},
3823
}
3924
}
4025

4126
func jetbrainsConfigCmd(c *components.Context) error {
42-
if c.GetNumberOfArgs() == 0 {
43-
return fmt.Errorf("repository URL is required\n\nUsage: jf rt jetbrains-config <repository-url>\nExample: jf rt jetbrains-config https://mycompany.jfrog.io/artifactory/api/jetbrainsplugins/jetbrains-plugins")
44-
}
45-
46-
repositoryURL := c.GetArgumentAt(0)
47-
if repositoryURL == "" {
48-
return fmt.Errorf("repository URL cannot be empty\n\nUsage: jf rt jetbrains-config <repository-url>")
27+
repositoryURL, err := ide.ValidateSingleNonEmptyArg(c, "jf jetbrains-config <repository-url>")
28+
if err != nil {
29+
return err
4930
}
5031

5132
// Extract repo key from repository URL for potential validation
@@ -54,10 +35,8 @@ func jetbrainsConfigCmd(c *components.Context) error {
5435
// Create server details only if server configuration flags are provided
5536
// This makes server configuration optional for basic JetBrains setup
5637
var rtDetails *config.ServerDetails
57-
var err error
5838

59-
// Check if any server configuration flags are provided
60-
if hasServerConfigFlags(c) {
39+
if ide.HasServerConfigFlags(c) {
6140
rtDetails, err = pluginsCommon.CreateArtifactoryDetailsByFlags(c)
6241
if err != nil {
6342
return fmt.Errorf("failed to create server configuration: %w", err)
@@ -72,39 +51,29 @@ func jetbrainsConfigCmd(c *components.Context) error {
7251
return jetbrainsCmd.Run()
7352
}
7453

75-
// hasServerConfigFlags checks if any server configuration flags are provided
76-
func hasServerConfigFlags(c *components.Context) bool {
77-
// Check for common server configuration flags
78-
return c.IsFlagSet("url") ||
79-
c.IsFlagSet("user") ||
80-
c.IsFlagSet("password") ||
81-
c.IsFlagSet("access-token") ||
82-
c.IsFlagSet("server-id")
83-
}
84-
8554
// extractRepoKeyFromRepositoryURL extracts the repository key from a JetBrains repository URL
8655
// Expected format: https://<server>/artifactory/api/jetbrainsplugins/<repo-key>
8756
func extractRepoKeyFromRepositoryURL(repositoryURL string) string {
8857
if repositoryURL == "" {
8958
return ""
9059
}
9160

92-
// Look for the pattern: /api/jetbrainsplugins/<repo-key>
93-
const prefix = "/api/jetbrainsplugins/"
94-
95-
startIdx := strings.Index(repositoryURL, prefix)
96-
if startIdx == -1 {
61+
// Parse the URL to extract the repository key
62+
parsedURL, err := url.Parse(repositoryURL)
63+
if err != nil {
9764
return ""
9865
}
99-
startIdx += len(prefix)
10066

101-
// Get everything after the prefix (until end of string or next slash)
102-
remaining := repositoryURL[startIdx:]
103-
endIdx := strings.Index(remaining, "/")
104-
if endIdx == -1 {
105-
// No trailing slash, use the rest of the string
106-
return remaining
67+
// Split the path to find the repository key
68+
// Expected path: /artifactory/api/jetbrainsplugins/<repo-key>
69+
pathParts := strings.Split(strings.TrimPrefix(parsedURL.Path, "/"), "/")
70+
71+
// Look for the jetbrainsplugins API path
72+
for i, part := range pathParts {
73+
if part == "api" && i+1 < len(pathParts) && pathParts[i+1] == "jetbrainsplugins" && i+2 < len(pathParts) {
74+
return pathParts[i+2]
75+
}
10776
}
10877

109-
return remaining[:endIdx]
78+
return ""
11079
}

0 commit comments

Comments
 (0)