From f6819bee3b57661c31e434acde34a00f52166383 Mon Sep 17 00:00:00 2001 From: Eyal Ben Moshe Date: Thu, 13 Apr 2023 12:01:01 +0300 Subject: [PATCH 01/25] Added the Frogbot badge to the README (#1901) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 11efbb8ad..807bf369d 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ # JFrog CLI +[![Scanned by Frogbot](https://raw.github.com/jfrog/frogbot/master/images/frogbot-badge.svg)](https://github.com/jfrog/frogbot#readme) [![Go Report Card](https://goreportcard.com/badge/github.com/jfrog/jfrog-cli)](https://goreportcard.com/report/github.com/jfrog/jfrog-cli) [![license](https://img.shields.io/badge/License-Apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/jfrog/jfrog-cli/v2/LICENSE) [![](https://img.shields.io/badge/Docs-%F0%9F%93%96-blue)](https://www.jfrog.com/confluence/display/CLI/JFrog+CLI) [![Go version](https://img.shields.io/github/go-mod/go-version/jfrog/jfrog-cli)](https://tip.golang.org/doc/go1.20) From 7e5aa5abb449b60beb29e3b7fd658dc825ee12db Mon Sep 17 00:00:00 2001 From: Eyal Ben Moshe Date: Mon, 8 May 2023 13:16:03 +0300 Subject: [PATCH 02/25] Add the `transfer-files` command to the docs (#1938) --- documentation/CLI-for-JFrog-Artifactory.md | 429 +++++++++++++----- .../images/transfer-files-progress.png | Bin 0 -> 166347 bytes .../images/transfer-files-status.png | Bin 0 -> 168152 bytes 3 files changed, 305 insertions(+), 124 deletions(-) create mode 100644 documentation/images/transfer-files-progress.png create mode 100644 documentation/images/transfer-files-status.png diff --git a/documentation/CLI-for-JFrog-Artifactory.md b/documentation/CLI-for-JFrog-Artifactory.md index 8c47bdfb5..713a3ec13 100644 --- a/documentation/CLI-for-JFrog-Artifactory.md +++ b/documentation/CLI-for-JFrog-Artifactory.md @@ -114,9 +114,9 @@ Symlinks are stored in Artifactory as files with a zero size, with the following **symlink.dest** - The actual path on the original filesystem to which the symlink points **symlink.destsha1** - the SHA1 checksum of the value in the **symlink.dest** property -To upload symlinks, the [upload command](#CLIforJFrogArtifactory-UploadingFiles) should be executed with the `--symlinks` option set to true. +To upload symlinks, the `jf rt upload` command should be executed with the `--symlinks` option set to true. -When downloading symlinks stored in Artifactory, the CLI can verify that the file to which the symlink points actually exists and that it has the correct SHA1 checksum. To add this validation, you should use the `--validate-symlinks`option with the [download command](#Downloading-Files). +When downloading symlinks stored in Artifactory, the CLI can verify that the file to which the symlink points actually exists and that it has the correct SHA1 checksum. To add this validation, you should use the `--validate-symlinks` option with the `jf rt download` command. * * * @@ -209,21 +209,21 @@ This command is used to upload files to Artifactory. | Command options | **Warning**

When using the * or ; characters in the upload command options or arguments, make sure to wrap the whole options or arguments string in quotes (") to make sure the * or ; characters are not interpreted as literals. | | --archive | \[Optional\]

Set to "zip" to pack and deploy the files to Artifactory inside a ZIP archive. Currently, the only packaging format supported is zip. | | --server-id | \[Optional\]

Server ID configured using the **jf c add** command. If not specified, the default configured Artifactory server is used. | -| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](#Using-File-Specs). | +| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](https://jfrog.com/help/r/jfrog-cli/using-file-specs). | | --spec-vars | \[Optional\]

List of variables in the form of "key1=value1;key2=value2;..." to be replaced in the File Spec. In the File Spec, the variables should be used as follows: ${key1}. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --target-props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon ( ; ) to be attached to the uploaded files. If any key can take several values, then each value is separated by a comma ( , ). For example, "key1=value1;key2=value21,value22;key3=value3". | | --deb | \[Optional\]

Used for Debian packages only. Specifies the distribution/component/architecture of the package. If the the value for distribution, component or architecture include a slash. the slash should be escaped with a back-slash. | -| --flat | \[Default: false\]

If true, files are uploaded to the exact target path specified and their hierarchy in the source file system is ignored.

If false, files are uploaded to the target path while maintaining their file system hierarchy.

If [placeholders](#Using-Placeholders) are used, the value of this option is ignored.

**Note**

**JFrog CLI v1**

In JFrog CLI v1, the default value of the --flat option is true. | +| --flat | \[Default: false\]

If true, files are uploaded to the exact target path specified and their hierarchy in the source file system is ignored.

If false, files are uploaded to the target path while maintaining their file system hierarchy.

If [Using Placeholders](https://jfrog.com/help/r/jfrog-cli/using-placeholders) are used, the value of this option is ignored.

**Note**

**JFrog CLI v1**

In JFrog CLI v1, the default value of the --flat option is true. | | --recursive | \[Default: true\]

If true, files are also collected from sub-folders of the source directory for upload .

If false, only files specifically in the source directory are uploaded. | | --regexp | \[Default: false\]

If true, the command will interpret the first argument, which describes the local file-system path of artifacts to upload, as a regular expression.

If false, it will interpret the first argument as a wild-card expression.

The above also applies for the --exclusions option.

If you have specified that you are using regular expressions, then the beginning of the expression must be enclosed in parenthesis. For example: **a/b/c/(.*)/file.zip** | | --ant | \[Default: false\]

If true, the command will interpret the first argument, which describes the local file-system path of artifacts to upload, as an ANT pattern.

If false, it will interpret the first argument as a wildcards expression.

The above also applies for the --exclusions option. | | --threads | \[Default: 3\]

The number of parallel threads that should be used to upload where each thread uploads a single artifact at a time. | | --dry-run | \[Default: false\]

If true, the command only indicates which artifacts would have been uploaded

If false, the command is fully executed and uploads artifacts as specified | -| --symlinks | \[Default: false\]

If true, the command will preserve the soft links structure in Artifactory. The **[symlink](#CLIforJFrogArtifactory-StoringSymlinksinArtifactory)** file representation will contain the symbolic link and checksum properties. | +| --symlinks | \[Default: false\]

If true, the command will preserve the soft links structure in Artifactory. The `symlink` file representation will contain the symbolic link and checksum properties. | | --explode | \[Default: false\]

If true, the command will extract an archive containing multiple artifacts after it is deployed to Artifactory, while maintaining the archive's file structure. | | --include-dirs | \[Default: false\]

If true, the source path applies to bottom-chain directories and not only to files. Bottom-chain directories are either empty or do not include other directories that match the source path. | | --exclusions | \[Optional\]

A list of Semicolon-separated exclude patterns. Allows using wildcards, regular expressions or ANT patterns, according to the value of the **--regexp** and **--ant** options. Please read the **--regexp** and **--ant** options description for more information. | @@ -236,7 +236,7 @@ This command is used to upload files to Artifactory. | --insecure-tls | \[Default: false\]

Set to true to skip TLS certificates verification. | | Command arguments | The command takes two arguments.

In case the --spec option is used, the commands accepts no arguments. | | Source path | The first argument specifies the local file system path to artifacts which should be uploaded to Artifactory. You can specify multiple artifacts by using wildcards or a regular expression as designated by the **--regexp** command option. Please read the **--regexp** option description for more information. | -| Target path | The second argument specifies the target path in Artifactory in the following format: `[repository name]/[repository path]`

If the target path ends with a slash, the path is assumed to be a folder. For example, if you specify the target as "repo-name/a/b/", then "b" is assumed to be a folder in Artifactory into which files should be uploaded. If there is no terminal slash, the target path is assumed to be a file to which the uploaded file should be renamed. For example, if you specify the target as "repo-name/a/b", the uploaded file is renamed to "b" in Artifactory.

For flexibility in specifying the upload path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding tokens in the source path that are enclosed in parenthesis. For more details, please refer to [Using Placeholders](#CLIforJFrogArtifactory-UsingPlaceholders)**.** | +| Target path | The second argument specifies the target path in Artifactory in the following format: `[repository name]/[repository path]`

If the target path ends with a slash, the path is assumed to be a folder. For example, if you specify the target as "repo-name/a/b/", then "b" is assumed to be a folder in Artifactory into which files should be uploaded. If there is no terminal slash, the target path is assumed to be a file to which the uploaded file should be renamed. For example, if you specify the target as "repo-name/a/b", the uploaded file is renamed to "b" in Artifactory.

For flexibility in specifying the upload path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding tokens in the source path that are enclosed in parenthesis. For more details, please refer to [Using Placeholders](https://jfrog.com/help/r/jfrog-cli/using-placeholders). | #### Examples @@ -295,48 +295,48 @@ This command is used to download files from Artifactory. > Download from Remote Repositories:

By default, the command only downloads files which are cached on the current Artifactory instance. It does not download files located on remote Artifactory instances, through remote or virtual repositories. To allow the command to download files from remote Artifactory instances, which are proxied by the use of remote repositories, set the **JFROG_CLI_TRANSITIVE_DOWNLOAD_EXPERIMENTAL** environment variable to **true**. This functionality requires version 7.17 or above of Artifactory. The remote download functionality is supported only on remote repositories which proxy repositories on remote Artifactory instances. Downloading through a remote repository which proxies non Artifactory repositories is not supported. -| | | -| --- | --- | -| Command name | rt download | -| Abbreviation | rt dl | -| Command options | **Warning**

When using the * or ; characters in the download command options or arguments, make sure to wrap the whole options or arguments string in quotes (") to make sure the * or ; characters are not interpreted as literals. | -| --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | -| --project | \[Optional\]

JFrog project key. | -| --module | \[Optional\]

Optional module name for the build-info. | -| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](#Using-File-Specs). | -| --spec-vars | \[Optional\]

List of variables in the form of "key1=value1;key2=value2;..." to be replaced in the File Spec. In the File Spec, the variables should be used as follows: ${key1}. | -| --props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts with **all** of the specified properties names and values will be downloaded. | -| --exclude-props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts **without all** of the specified properties names and values will be downloaded. | -| --build | \[Optional\]

If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number. | -| --bundle | \[Optional\]

If specified, only artifacts of the specified bundle are matched. The value format is bundle-name/bundle-version. | -| --flat | \[Default: false\]

If true, artifacts are downloaded to the exact target path specified and their hierarchy in the source repository is ignored.

If false, artifacts are downloaded to the target path in the file system while maintaining their hierarchy in the source repository.

If [placeholders](#Using-Placeholders) are used, and you would like the local file-system (download path) to be determined by placeholders only, or in other words, avoid concatenating the Artifactory folder hierarchy local, set to false. | -| --recursive | \[Default: true\]

If true, artifacts are also downloaded from sub-paths under the specified path in the source repository.

If false, only artifacts in the specified source path directory are downloaded. | -| --threads | \[Default: 3\]

The number of parallel threads that should be used to download where each thread downloads a single artifact at a time. | -| --split-count | \[Default: 3\]

The number of segments into which each file should be split for download (provided the artifact is over `--min-split` in size). To download each file in a single thread, set to 0. | -| --retries | \[Default: 3\]

Number of download retries. | -| --retry-wait-time | \[Default: 0s\]

Number of seconds or milliseconds to wait between retries. The numeric value should either end with s for seconds or ms for milliseconds. | -| --min-split | \[Default: 5120\]

The minimum size permitted for splitting. Files larger than the specified number will be split into equally sized `--split-count` segments. Any files smaller than the specified number will be downloaded in a single thread. If set to -1, files are not split. | -| --dry-run | \[Default: false\]

If true, the command only indicates which artifacts would have been downloaded.

If false, the command is fully executed and downloads artifacts as specified. | -| --explode | \[Default: false\]

Set to true to extract an archive after it is downloaded from Artifactory.

Supported compression formats: br, bz2, gz, lz4, sz, xz, zstd.

Supported archive formats: zip, tar (including any compressed variants like tar.gz), rar. | -| --validate-symlinks | \[Default: false\]

If true, the command will validate that **[symlinks](#CLIforJFrogArtifactory-StoringSymlinksinArtifactory)** are pointing to existing and unchanged files, by comparing their sha1. Applicable to files and not directories. | -| --include-dirs | \[Default: false\]

If true, the source path applies to bottom-chain directories and not only to files. Bottom-chain directories are either empty or do not include other directories that match the source path. | -| --exclusions | A list of Semicolon-separated exclude patterns. Allows using wildcards. | -| --sync-deletes | \[Optional\]

Specific path in the local file system, under which to sync dependencies after the download. After the download, this path will include only the dependencies downloaded during this download operation. The other files under this path will be deleted. | -| --quiet | \[Default: false\]

If true, the delete confirmation message is skipped. | -| --sort-by | \[Optional\]

A list of semicolon-separated fields to sort by. The fields must be part of the 'items' AQL domain. For more information read the [AQL documentation](https://jfrog.com/help/r/jfrog-artifactory-documentation/Artifactory-Query-Language) | -| --sort-order | \[Default: asc\]

The order by which fields in the 'sort-by' option should be sorted. Accepts 'asc' or 'desc'. | -| --limit | \[Optional\]

The maximum number of items to fetch. Usually used with the 'sort-by' option. | -| --offset | \[Optional\]

The offset from which to fetch items (i.e. how many items should be skipped). Usually used with the 'sort-by' option. | -| --fail-no-op | \[Default: false\]

Set to true if you'd like the command to return exit code 2 in case of no files are affected. | -| --archive-entries | \[Optional\]

If specified, only archive artifacts containing entries matching this pattern are matched. You can use wildcards to specify multiple artifacts. | -| --detailed-summary | \[Default: false\]

Set to true to include a list of the affected files as part of the command output summary. | -| --insecure-tls | \[Default: false\]

Set to true to skip TLS certificates verification. | -| --gpg-key | \[Optional\]

Path to the public GPG key file located on the file system, used to validate downloaded release bundle files. | -| Command arguments | | -| Source path | Specifies the source path in Artifactory, from which the artifacts should be downloaded. You can use wildcards to specify multiple artifacts. | -| Target path | The second argument is optional and specifies the local file system target path.

If the target path ends with a slash, the path is assumed to be a directory. For example, if you specify the target as "repo-name/a/b/", then "b" is assumed to be a directory into which files should be downloaded. If there is no terminal slash, the target path is assumed to be a file to which the downloaded file should be renamed. For example, if you specify the target as "a/b", the downloaded file is renamed to "b".

For flexibility in specifying the target path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding tokens in the source path that are enclosed in parenthesis. For more details, please refer to [Using Placeholders](#CLIforJFrogArtifactory-UsingPlaceholders)**.** | +| | | +| --- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Command name | rt download | +| Abbreviation | rt dl | +| Command options | **Warning**

When using the * or ; characters in the download command options or arguments, make sure to wrap the whole options or arguments string in quotes (") to make sure the * or ; characters are not interpreted as literals. | +| --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --project | \[Optional\]

JFrog project key. | +| --module | \[Optional\]

Optional module name for the build-info. | +| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](https://jfrog.com/help/r/jfrog-cli/using-file-specs). | +| --spec-vars | \[Optional\]

List of variables in the form of "key1=value1;key2=value2;..." to be replaced in the File Spec. In the File Spec, the variables should be used as follows: ${key1}. | +| --props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts with **all** of the specified properties names and values will be downloaded. | +| --exclude-props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts **without all** of the specified properties names and values will be downloaded. | +| --build | \[Optional\]

If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number. | +| --bundle | \[Optional\]

If specified, only artifacts of the specified bundle are matched. The value format is bundle-name/bundle-version. | +| --flat | \[Default: false\]

If true, artifacts are downloaded to the exact target path specified and their hierarchy in the source repository is ignored.

If false, artifacts are downloaded to the target path in the file system while maintaining their hierarchy in the source repository.

If [Using Placeholders](https://jfrog.com/help/r/jfrog-cli/using-placeholders) are used, and you would like the local file-system (download path) to be determined by placeholders only, or in other words, avoid concatenating the Artifactory folder hierarchy local, set to false. | +| --recursive | \[Default: true\]

If true, artifacts are also downloaded from sub-paths under the specified path in the source repository.

If false, only artifacts in the specified source path directory are downloaded. | +| --threads | \[Default: 3\]

The number of parallel threads that should be used to download where each thread downloads a single artifact at a time. | +| --split-count | \[Default: 3\]

The number of segments into which each file should be split for download (provided the artifact is over `--min-split` in size). To download each file in a single thread, set to 0. | +| --retries | \[Default: 3\]

Number of download retries. | +| --retry-wait-time | \[Default: 0s\]

Number of seconds or milliseconds to wait between retries. The numeric value should either end with s for seconds or ms for milliseconds. | +| --min-split | \[Default: 5120\]

The minimum size permitted for splitting. Files larger than the specified number will be split into equally sized `--split-count` segments. Any files smaller than the specified number will be downloaded in a single thread. If set to -1, files are not split. | +| --dry-run | \[Default: false\]

If true, the command only indicates which artifacts would have been downloaded.

If false, the command is fully executed and downloads artifacts as specified. | +| --explode | \[Default: false\]

Set to true to extract an archive after it is downloaded from Artifactory.

Supported compression formats: br, bz2, gz, lz4, sz, xz, zstd.

Supported archive formats: zip, tar (including any compressed variants like tar.gz), rar. | +| --validate-symlinks | \[Default: false\]

If true, the command will validate that **symlinks** are pointing to existing and unchanged files, by comparing their sha1. Applicable to files and not directories. | +| --include-dirs | \[Default: false\]

If true, the source path applies to bottom-chain directories and not only to files. Bottom-chain directories are either empty or do not include other directories that match the source path. | +| --exclusions | A list of Semicolon-separated exclude patterns. Allows using wildcards. | +| --sync-deletes | \[Optional\]

Specific path in the local file system, under which to sync dependencies after the download. After the download, this path will include only the dependencies downloaded during this download operation. The other files under this path will be deleted. | +| --quiet | \[Default: false\]

If true, the delete confirmation message is skipped. | +| --sort-by | \[Optional\]

A list of semicolon-separated fields to sort by. The fields must be part of the 'items' AQL domain. For more information read the [AQL documentation](https://jfrog.com/help/r/jfrog-artifactory-documentation/Artifactory-Query-Language) | +| --sort-order | \[Default: asc\]

The order by which fields in the 'sort-by' option should be sorted. Accepts 'asc' or 'desc'. | +| --limit | \[Optional\]

The maximum number of items to fetch. Usually used with the 'sort-by' option. | +| --offset | \[Optional\]

The offset from which to fetch items (i.e. how many items should be skipped). Usually used with the 'sort-by' option. | +| --fail-no-op | \[Default: false\]

Set to true if you'd like the command to return exit code 2 in case of no files are affected. | +| --archive-entries | \[Optional\]

If specified, only archive artifacts containing entries matching this pattern are matched. You can use wildcards to specify multiple artifacts. | +| --detailed-summary | \[Default: false\]

Set to true to include a list of the affected files as part of the command output summary. | +| --insecure-tls | \[Default: false\]

Set to true to skip TLS certificates verification. | +| --gpg-key | \[Optional\]

Path to the public GPG key file located on the file system, used to validate downloaded release bundle files. | +| Command arguments | | +| Source path | Specifies the source path in Artifactory, from which the artifacts should be downloaded. You can use wildcards to specify multiple artifacts. | +| Target path | The second argument is optional and specifies the local file system target path.

If the target path ends with a slash, the path is assumed to be a directory. For example, if you specify the target as "repo-name/a/b/", then "b" is assumed to be a directory into which files should be downloaded. If there is no terminal slash, the target path is assumed to be a file to which the downloaded file should be renamed. For example, if you specify the target as "a/b", the downloaded file is renamed to "b".

For flexibility in specifying the target path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding tokens in the source path that are enclosed in parenthesis. For more details, please refer to [Using Placeholders](https://jfrog.com/help/r/jfrog-cli/using-placeholders). | #### Examples @@ -378,7 +378,7 @@ This command is used to copy files in Artifactory | Abbreviation | rt cp | | Command options | **Warning**

When using the * or ; characters in the copy command options or arguments, make sure to wrap the whole options or arguments string in quotes (") to make sure the * or ; characters are not interpreted as literals. | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](#CLIforJFrogArtifactory-UsingFileSpecs). | +| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](https://jfrog.com/help/r/jfrog-cli/using-file-specs). | | --props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon. (For example, "key1=value1;key2=value2;key3=value3"). Only artifacts with these properties names and values will be copied. | | --exclude-props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts **without all** of the specified properties names and values will be copied. | | --build | \[Optional\]

If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number. | @@ -399,7 +399,7 @@ This command is used to copy files in Artifactory | --retry-wait-time | \[Default: 0s\]

Number of seconds or milliseconds to wait between retries. The numeric value should either end with s for seconds or ms for milliseconds. | | Command arguments | The command takes two arguments | | Source path | Specifies the source path in Artifactory, from which the artifacts should be copied, in the following format: `[repository name]/[repository path].` You can use wildcards to specify multiple artifacts. | -| Target path | Specifies the target path in Artifactory, to which the artifacts should be copied, in the following format: `[repository name]/[repository path]`

If the pattern ends with a slash, the target path is assumed to be a folder. For example, if you specify the target as "repo-name/a/b/", then "b" is assumed to be a folder in Artifactory into which files should be copied. If there is no terminal slash, the target path is assumed to be a file to which the copied file should be renamed. For example, if you specify the target as "repo-name/a/b", the copied file is renamed to "b" in Artifactory.

For flexibility in specifying the target path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding tokens in the source path that are enclosed in parenthesis. For more details, please refer to [Using Placeholders](#Using-Placeholders)**.** | +| Target path | Specifies the target path in Artifactory, to which the artifacts should be copied, in the following format: `[repository name]/[repository path]`

If the pattern ends with a slash, the target path is assumed to be a folder. For example, if you specify the target as "repo-name/a/b/", then "b" is assumed to be a folder in Artifactory into which files should be copied. If there is no terminal slash, the target path is assumed to be a file to which the copied file should be renamed. For example, if you specify the target as "repo-name/a/b", the copied file is renamed to "b" in Artifactory.

For flexibility in specifying the target path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding tokens in the source path that are enclosed in parenthesis. For more details, please refer to [Using Placeholders](https://jfrog.com/help/r/jfrog-cli/using-placeholders). | #### Examples @@ -434,7 +434,7 @@ This command is used to move files in Artifactory | Abbreviation | rt mv | | Command options | **Warning**

When using the * or ; characters in the copy command options or arguments, make sure to wrap the whole options or arguments string in quotes (") to make sure the * or ; characters are not interpreted as literals. | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](#CLIforJFrogArtifactory-UsingFileSpecs). | +| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](https://jfrog.com/help/r/jfrog-cli/using-file-specs). | | --props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts with these properties names and values will be moved. | | --exclude-props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts **without all** of the specified properties names and values will be moved. | | --build | \[Optional\]

If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number. | @@ -455,7 +455,7 @@ This command is used to move files in Artifactory | --retry-wait-time | \[Default: 0s\]

Number of seconds or milliseconds to wait between retries. The numeric value should either end with s for seconds or ms for milliseconds. | | Command arguments | The command takes two arguments | | Source path | Specifies the source path in Artifactory, from which the artifacts should be moved, in the following format: `[repository name]/[repository path].` You can use wildcards to specify multiple artifacts. | -| Target path | Specifies the target path in Artifactory, to which the artifacts should be moved, in the following format: `[repository name]/[repository path]`

If the pattern ends with a slash, the target path is assumed to be a folder. For example, if you specify the target as "repo-name/a/b/", then "b" is assumed to be a folder in Artifactory into which files should be moved. If there is no terminal slash, the target path is assumed to be a file to which the moved file should be renamed. For example, if you specify the target as "repo-name/a/b", the moved file is renamed to "b" in Artifactory.

For flexibility in specifying the upload path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding tokens in the source path that are enclosed in parenthesis. For more details, please refer to [Using Placeholders](#Using-Placeholders)**.** | +| Target path | Specifies the target path in Artifactory, to which the artifacts should be moved, in the following format: `[repository name]/[repository path]`

If the pattern ends with a slash, the target path is assumed to be a folder. For example, if you specify the target as "repo-name/a/b/", then "b" is assumed to be a folder in Artifactory into which files should be moved. If there is no terminal slash, the target path is assumed to be a file to which the moved file should be renamed. For example, if you specify the target as "repo-name/a/b", the moved file is renamed to "b" in Artifactory.

For flexibility in specifying the upload path, you can include placeholders in the form of {1}, {2} which are replaced by corresponding tokens in the source path that are enclosed in parenthesis. For more details, please refer to [Using Placeholders](https://jfrog.com/help/r/jfrog-cli/using-placeholders). | #### Examples @@ -490,7 +490,7 @@ This command is used to delete files in Artifactory | Abbreviation | rt del | | Command options | **Warning**

When using the * or ; characters in the delete command options or arguments, make sure to wrap the whole options or arguments string in quotes (") to make sure the * or ; characters are not interpreted as literals. | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](#CLIforJFrogArtifactory-UsingFileSpecs). | +| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](https://jfrog.com/help/r/jfrog-cli/using-file-specs). | | --props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts with these properties names and values will be deleted. | | --exclude-props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts **without all** of the specified properties names and values will be deleted. | | --build | \[Optional\]

If specified, only artifacts of the specified build are matched. The property format is build-name/build-number. If you do not specify the build number, the artifacts are filtered by the latest build number. | @@ -538,7 +538,7 @@ This command is used to search and display files in Artifactory. | Abbreviation | rt s | | Command options | **Warning**

When using the * or ; characters in the command options or arguments, make sure to wrap the whole options or arguments string in quotes (") to make sure the * or ; characters are not interpreted as literals. | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](#CLIforJFrogArtifactory-UsingFileSpecs). | +| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](https://jfrog.com/help/r/jfrog-cli/using-file-specs). | | --count | \[Optional\]

Set to true to display only the total of files or folders found. | | --include-dirs | \[Optional\]

Set to true if you'd like to also apply the source path pattern for directories and not only for files | | --spec-vars | \[Optional\]

List of variables in the form of "key1=value1;key2=value2;..." to be replaced in the File Spec. In the File Spec, the variables should be used as follows: ${key1}. | @@ -587,7 +587,7 @@ This command is used for setting properties on existing files in Artifactory. | Abbreviation | rt sp | | Command options | **Warning**

When using the * or ; characters in the command options or arguments, make sure to wrap the whole options or arguments string in quotes (") to make sure the * or ; characters are not interpreted as literals. | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](#CLIforJFrogArtifactory-UsingFileSpecs). | +| --spec | \[Optional\]

Path to a file spec. For more details, please refer to [Using File Specs](https://jfrog.com/help/r/jfrog-cli/using-file-specs). | | --spec-vars | \[Optional\]

List of variables in the form of "key1=value1;key2=value2;..." to be replaced in the File Spec. In the File Spec, the variables should be used as follows: ${key1}. | | --props | \[Optional\]

List of properties in the form of "key1=value1;key2=value2,...". Only files with these properties names and values are affected. | | --exclude-props | \[Optional\]

A list of Artifactory [properties](https://jfrog.com/help/r/jfrog-artifactory-documentation/Working-With-Jfrog-Properties) specified as "key=value" pairs separated by a semi-colon (for example, "key1=value1;key2=value2;key3=value3"). Only artifacts **without all** of the specified properties names and values will be affected. | @@ -760,15 +760,15 @@ JFrog CLI integrates with any development ecosystem allowing you to collect buil Many of JFrog CLI's commands accept two optional command options: **--build-name** and **--build-number**. When these options are added, JFrog CLI collects and records the build info locally for these commands. When running multiple commands using the same build and build number, JFrog CLI aggregates the collected build info into one build. -The recorded build-info can be later published to Artifactory using the [build-publish](#Publishing-Build-Information) command. +The recorded build-info can be later published to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. ### Collecting Build-Info -Build-info is collected by adding the `--build-name` and `--build-number` options to different CLI commands. The CLI commands can be run several times and cumulatively collect build-info for the specified build name and number until it is published to Artifactory. For example, running the [download](#Downloading-Files) command several times with the same build name and number will accumulate each downloaded file in the corresponding build-info. +Build-info is collected by adding the `--build-name` and `--build-number` options to different CLI commands. The CLI commands can be run several times and cumulatively collect build-info for the specified build name and number until it is published to Artifactory. For example, running the `jf rt download` command several times with the same build name and number will accumulate each downloaded file in the corresponding build-info. #### Collecting Dependencies -Dependencies are collected by adding the `--build-name` and `--build-number` options to the [download](#Downloading-Files) command. +Dependencies are collected by adding the `--build-name` and `--build-number` options to the `jf rt download` command. For example, the following command downloads the `cool-froggy.zip` file found in repository `my-local-repo`, but it also specifies this file as a dependency in build `my-build-name` with build number 18: ``` @@ -776,7 +776,7 @@ jf rt dl my-local-repo/cool-froggy.zip --build-name=my-build-name --build-number ``` #### Collecting Build Artifacts -Build artifacts are collected by adding the `--build-name` and `--build-number` options to the [upload](#CLIforJFrogArtifactory-UploadingFiles) command. +Build artifacts are collected by adding the `--build-name` and `--build-number` options to the `jf rt upload` command. For example, the following command specifies that file `froggy.tgz` uploaded to repository `my-local-repo` is a build artifact of build `my-build-name` with build number 18: ``` @@ -815,18 +815,18 @@ The `build-add-git` (bag) command collects the Git revision and URL from the loc The following table lists the command arguments and flags: -| | | -| --- | --- | -| Command name | rt build-add-git | -| Abbreviation | rt bag | -| Command options | | -| --config | \[Optional\]

Path to a yaml configuration file, used for collecting tracked project issues and adding them to the build-info. | -| --server-id | \[Optional\]

Server ID configured using the ['jf config' command](https://jfrog.com/help/r/jfrog-cli/jfrog-Platform-CONFIGURATION). This is the server to which the build-info will be later published, using the [`build-publish` (`bp`)](#Publishing Build-Info) command. This option, if provided, overrides the serverID value in this command's yaml configuration. If both values are not provided, the default server, configured by the ['jf config' command](https://jfrog.com/help/r/jfrog-cli/jfrog-Platform-CONFIGURATION), is used. | -| --project | \[Optional\]

JFrog project key. | -| Command arguments | The command accepts three arguments. | -| Build name | Build name. | -| Build number | Build number. | -| .git path | Optional - Path to a directory containing the .git directory. If not specific, the .git directory is assumed to be in the current directory or in one of the parent directories. | +| | | +| --- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Command name | rt build-add-git | +| Abbreviation | rt bag | +| Command options | | +| --config | \[Optional\]

Path to a yaml configuration file, used for collecting tracked project issues and adding them to the build-info. | +| --server-id | \[Optional\]

Server ID configured using the ['jf config' command](https://jfrog.com/help/r/jfrog-cli/jfrog-Platform-CONFIGURATION). This is the server to which the build-info will be later published, using the `jf rt build-publish` command. This option, if provided, overrides the serverID value in this command's yaml configuration. If both values are not provided, the default server, configured by the ['jf config' command](https://jfrog.com/help/r/jfrog-cli/jfrog-Platform-CONFIGURATION), is used. | +| --project | \[Optional\]

JFrog project key. | +| Command arguments | The command accepts three arguments. | +| Build name | Build name. | +| Build number | Build number. | +| .git path | Optional - Path to a directory containing the .git directory. If not specific, the .git directory is assumed to be in the current directory or in one of the parent directories. | ##### Example ``` @@ -1057,7 +1057,7 @@ jf rt bc my-build-name 18 ### Discarding Old Builds from Artifactory -This command is used to discard builds previously published to Artifactory using the [build-publish](#Publishing-Build-Information) command. +This command is used to discard builds previously published to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. The following table lists the command arguments and flags: @@ -1133,7 +1133,7 @@ The **mvn** command triggers the maven client, while resolving dependencies and > **Note**: Before running the **mvn** command on a project for the first time, the project should be configured with the **mvn-config** command. -> **Note**: If the machine running JFrog CLI has no access to the internet, make sure to read the [Downloading the Maven and Gradle Extractor JARs](#CLIforJFrogArtifactory-DownloadingtheMavenandGradleExtractorJARs) section. +> **Note**: If the machine running JFrog CLI has no access to the internet, make sure to read the [Downloading the Maven and Gradle Extractor JARs](https://jfrog.com/help/r/jfrog-cli/downloading-the-maven-and-gradle-extractor-jars) section. The following table lists the command arguments and flags: @@ -1143,8 +1143,8 @@ The following table lists the command arguments and flags: | Abbreviation | mvn | | Command options | | | --threads | \[Default: 3\]

Number of threads for uploading build artifacts. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --insecure-tls | \[Default: false\]

Set to true to skip TLS certificates verification. | | Command arguments | The command accepts the same arguments and options as the mvn client. | @@ -1198,7 +1198,7 @@ The **gradle** command triggers the gradle client, while resolving dependencies > **Note**: Before running the **gradle** command on a project for the first time, the project should be configured with the **gradle-config** command. -> **Note**: If the machine running JFrog CLI has no access to the internet, make sure to read the[Downloading the Maven and Gradle Extractor JARs](#CLIforJFrogArtifactory-DownloadingtheMavenandGradleExtractorJARs)section. +> **Note**: If the machine running JFrog CLI has no access to the internet, make sure to read the[Downloading the Maven and Gradle Extractor JARs](https://jfrog.com/help/r/jfrog-cli/downloading-the-maven-and-gradle-extractor-jars)section. The following table lists the command arguments and flags: @@ -1208,8 +1208,8 @@ The following table lists the command arguments and flags: | Abbreviation | gradle | | Command options | | | --threads | \[Default: 3\]

Number of threads for uploading build artifacts. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | + | --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | Command arguments | The command accepts the same arguments and options as the gradle client. | @@ -1255,7 +1255,7 @@ Check out our [docker project examples on GitHub](https://github.com/jfrog/proje #### Pulling Docker Images Using the Docker Client -Running **docker-pull** command allows pulling docker images from Artifactory, while collecting the build-info and storing it locally, so that it can be later published to Artifactory, using the [build](#Publishing-Build-Information)****-publish** command. +Running **docker-pull** command allows pulling docker images from Artifactory, while collecting the build-info and storing it locally, so that it can be later published to Artifactory, using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. The following table lists the command arguments and flags: @@ -1267,8 +1267,8 @@ The following table lists the command arguments and flags: | Abbreviation | dpl | | Command options | | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --skip-login | \[Default: false\]

Set to true if you'd like the command to skip performing docker login. | @@ -1278,7 +1278,7 @@ The following table lists the command arguments and flags: jf docker pull my-docker-registry.io/my-docker-image:latest --build-name=my-build-name --build-number=7 -You can then publish the build-info collected by the **docker-pull** command to Artifactory using the [build-publish](#Publishing-Build-Information) command. +You can then publish the build-info collected by the **docker-pull** command to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. @@ -1296,8 +1296,8 @@ The following table lists the command arguments and flags: | Abbreviation | dp | | Command options | | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --skip-login | \[Default: false\]

Set to true if you'd like the command to skip performing docker login. | @@ -1309,13 +1309,13 @@ The following table lists the command arguments and flags: jf docker push my-docker-registry.io/my-docker-image:latest --build-name=my-build-name --build-number=7 -You can then publish the build-info collected by the **docker-push** command to Artifactory using the [build-publish](#Publishing-Build-Information) command. +You can then publish the build-info collected by the **docker-push** command to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. #### Pulling Docker Images Using Podman -[Podman](https://podman.io/) is a daemonless container engine for developing, managing, and running OCI Containers. Running the **podman-pull** command allows pulling docker images from Artifactory using podman, while collecting the build-info and storing it locally, so that it can be later published to Artifactory, using the [build-publish](#Publishing-Build-Information) command. +[Podman](https://podman.io/) is a daemonless container engine for developing, managing, and running OCI Containers. Running the **podman-pull** command allows pulling docker images from Artifactory using podman, while collecting the build-info and storing it locally, so that it can be later published to Artifactory, using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. The following table lists the command arguments and flags: @@ -1325,8 +1325,8 @@ The following table lists the command arguments and flags: | Abbreviation | rt ppl | | Command options | | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --skip-login | \[Default: false\]

Set to true if you'd like the command to skip performing docker login. | @@ -1338,7 +1338,7 @@ The following table lists the command arguments and flags: ``` jf rt podman-pull my-docker-registry.io/my-docker-image:latest docker-local --build-name=my-build-name --build-number=7 ``` -You can then publish the build-info collected by the **podman-pull** command to Artifactory using the [build-publish](#Publishing-Build-Information) command. +You can then publish the build-info collected by the **podman-pull** command to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. @@ -1356,8 +1356,8 @@ The following table lists the command arguments and flags: | Abbreviation | rt pp | | Command options | | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --skip-login | \[Default: false\]

Set to true if you'd like the command to skip performing docker login. | @@ -1371,7 +1371,7 @@ The following table lists the command arguments and flags: ``` jf rt podman-push my-docker-registry.io/my-docker-image:latest docker-local --build-name=my-build-name --build-number=7 ``` -You can then publish the build-info collected by the **podman-push** command to Artifactory using the [build-publish](#Publishing-Build-Information) command. +You can then publish the build-info collected by the **podman-push** command to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. @@ -1405,8 +1405,8 @@ The **build-docker-create** command allows adding a docker image, which is alrea | Command options | | | --image-file | Path to a file which includes one line in the following format: IMAGE-TAG@sha256:MANIFEST-SHA256. For example:

cat image-file-details
superfrog-docker.jfrog.io/hello-frog@sha256:30f04e684493fb5ccc030969df6de0 | | --server-id | \[Optional\]

Server ID configured using the config command. If not specified, the default configured Artifactory server is used. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --skip-login | \[Default: false\]

Set to true if you'd like the command to skip performing docker login. | @@ -1418,7 +1418,7 @@ The **build-docker-create** command allows adding a docker image, which is alrea ``` jf rt bdc docker-local --image-file image-file-details --build-name myBuild --build-number 1 ``` -You can then publish the build-info collected by the **podman-push** command to Artifactory using the [build-publish](#Publishing-Build-Information) command. +You can then publish the build-info collected by the **podman-push** command to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. @@ -1499,8 +1499,8 @@ The following table lists the command arguments and flags: | Command-name | npm | | Abbreviation | | | Command options | | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --threads | \[Default: 3\]

Number of working threads for build-info collection. | @@ -1510,7 +1510,7 @@ The following table lists the command arguments and flags: ##### Example 1 -The following example installs the dependencies and records them locally as part of build **my-build-name/1**. The build-info can later be published to Artifactory using the [build-publish](#Publishing-Build-Information) command. The dependencies are resolved from the Artifactory server and repository configured by **npm-config** command. +The following example installs the dependencies and records them locally as part of build **my-build-name/1**. The build-info can later be published to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. The dependencies are resolved from the Artifactory server and repository configured by **npm-config** command. ``` jf npm install --build-name=my-build-name --build-number=1 ``` @@ -1545,8 +1545,8 @@ The following table lists the command arguments and flags: | Command-name | npm publish | | Abbreviation | | | Command options | | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --detailed-summary | \[Default: false\]

Set true to include a list of the affected files as part of the command output summary. | @@ -1556,7 +1556,7 @@ The following table lists the command arguments and flags: ##### Example -To pack and publish the npm package and also record it locally as part of build **my-build-name/1**, run the following command. The build-info can later be published to Artifactory using the [build-publish](#Publishing-Build-Information) command. The package is published to the Artifactory server and repository configured by **npm-config** command. +To pack and publish the npm package and also record it locally as part of build **my-build-name/1**, run the following command. The build-info can later be published to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. The package is published to the Artifactory server and repository configured by **npm-config** command. ``` jf npm publish --build-name=my-build-name --build-number=1 ``` @@ -1593,8 +1593,8 @@ The following table lists the command arguments and flags: | --- |--------------------------------------------------------------------------------------------------------------| | Command-name | yarn | | Command options | | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --threads | \[Default: 3\]

Number of working threads for build-info collection. | @@ -1604,7 +1604,7 @@ The following table lists the command arguments and flags: ##### Example 1 -The following example installs the dependencies and records them locally as part of build **my-build-name/1**. The build-info can later be published to Artifactory using the [build-publish](#Publishing-Build-Information) command. The dependencies are resolved from the Artifactory server and repository configured by **yarn-config command. +The following example installs the dependencies and records them locally as part of build **my-build-name/1**. The build-info can later be published to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. The dependencies are resolved from the Artifactory server and repository configured by **yarn-config command. ``` jf yarn install --build-name=my-build-name --build-number=1 ``` @@ -1688,8 +1688,8 @@ The following table lists the command arguments and flags: | Command-name | go | | Abbreviation | go | | Command options | | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --no-fallback | \[Default: false\]

Set to avoid downloading packages from the VCS, if they are missing in Artifactory. | | --module | \[Optional\]

Optional module name for the build-info. | @@ -1710,7 +1710,7 @@ jf rt go build ##### Example 2 -The following example runs Go build command, while recording the build-info locally under build name **my-build** and build number **1**. The build-info can later be published to Artifactory using the [build-publish](#Publishing-Build-Information)command. +The following example runs Go build command, while recording the build-info locally under build name **my-build** and build number **1**. The build-info can later be published to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info)command. > **Note**: Before using this example, please make sure to set repositories for the Go project using the go-config command. ``` @@ -1733,8 +1733,8 @@ The following table lists the command arguments and flags: | Command-name | go-publish | | Abbreviation | gp | | Command options | | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | --detailed-summary | \[Default: false\]

Set true to include a list of the affected files as part of the command output summary. | @@ -1752,7 +1752,7 @@ jf gp v1.2.3 ##### Example 2 -To pack and publish the Go package and also record the build-info as part of build **my-build-name/1** , run the following command. The build-info can later be published to Artifactory using the [build-publish](#Publishing-Build-Information) command. Before running this command on a project for the first time, the project should be configured using the **go-config** command. +To pack and publish the Go package and also record the build-info as part of build **my-build-name/1** , run the following command. The build-info can later be published to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command. Before running this command on a project for the first time, the project should be configured using the **go-config** command. ``` jf gp v1.2.3 --build-name my-build-name --build-number 1 ``` @@ -1850,8 +1850,8 @@ Running the install command with both the **no-cache-dir** and **force-reinstall | Command-name | pip / pipenv / poetry | | Abbreviation | | | Command options | | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | Command argument | | @@ -1885,9 +1885,9 @@ jf poetry install . --build-name my-build --build-number 1 JFrog CLI provides full support for restoring NuGet packages using the NuGet client or the .NET Core CLI. This allows you to resolve NuGet dependencies from and publish your NuGet packages to Artifactory, while collecting build-info and storing it in Artifactory. -NuGet dependencies resolution is supported by the [jf rt nuget](#Running-Nuget-commands) command, which uses the NuGet client or the [jf rt dotnet](#Running-Nuget-commands) command, which uses the .NET Core CLI. +NuGet dependencies resolution is supported by the `jf nuget` command, which uses the NuGet client or the `jf dotnet` command, which uses the .NET Core CLI. -To publish your NuGet packages to Artifactory, use the [jf rt upload](#Uploading-Files) command. +To publish your NuGet packages to Artifactory, use the [jf rt upload](https://jfrog.com/help/r/jfrog-cli/uploading-files) command. #### Setting NuGet repositories @@ -1923,8 +1923,8 @@ The following table lists the commands arguments and options: | Command-name | nuget / dotnet | | Abbreviation | | | Command options | | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | \[Optional\]

JFrog project key. | | --module | \[Optional\]

Optional module name for the build-info. | | Command argument | The command accepts the same arguments and options as the NuGet client / .NET Core CLI. | @@ -1949,7 +1949,7 @@ jf dotnet restore Run dotnet restore for the solution at the current directory, while resolving the NuGet dependencies from the pre-configured Artifactory repository. -In addition, record the build-info as part of build **my-build-name/1**. The build-info can later be published to Artifactory using the [build-publish](#Publishing-Build-Information) command: +In addition, record the build-info as part of build **my-build-name/1**. The build-info can later be published to Artifactory using the [build-publish](https://jfrog.com/help/r/jfrog-cli/publishing-build-info) command: ``` jf dotnet restore --build-name=my-build-name --build-number=1 ``` @@ -2009,8 +2009,8 @@ The following table lists the commands arguments and options: | --provider | \[Mandatory\]

Terraform module provider | | --tag | \[Mandatory\]

Terraform module tag | | --exclusions | \[Optional\]

A list of Semicolon-separated exclude patterns wildcards. Paths inside the module matching one of the patterns are excluded from the deployed package. | -| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](#Build-Integration). | -| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](#Build-Integration). | +| --build-name | \[Optional\]

Build name. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | +| --build-number | \[Optional\]

Build number. For more details, please refer to [Build Integration](https://jfrog.com/help/r/jfrog-cli/build-integration). | | --project | | | Command argument | The command accepts no arguments | @@ -2758,7 +2758,7 @@ The following File Spec finds all the folders which match the following criteria ###### Example 12 -This example uses [placeholders](#Using-Placeholders). For each .tgz file in the source directory, create a corresponding directory with the same name in the target repository and upload it there. For example, a file named froggy.tgz should be uploaded to my-local-rep/froggy. (froggy will be created a folder in Artifactory). +This example uses [Using Placeholders](https://jfrog.com/help/r/jfrog-cli/using-placeholders). For each .tgz file in the source directory, create a corresponding directory with the same name in the target repository and upload it there. For example, a file named froggy.tgz should be uploaded to my-local-rep/froggy. (froggy will be created a folder in Artifactory). ``` { "files": [ @@ -2773,7 +2773,7 @@ This example uses [placeholders](#Using-Placeholders). For each .tgz file in the ###### Example 13 -This examples uses [placeholders](#Using-Placeholders). Upload all files whose name begins with "frog" to folder frogfiles in the target repository, but append its name with the text "-up". For example, a file called froggy.tgz should be renamed froggy.tgz-up. +This examples uses [Using Placeholders](https://jfrog.com/help/r/jfrog-cli/using-placeholders). Upload all files whose name begins with "frog" to folder frogfiles in the target repository, but append its name with the text "-up". For example, a file called froggy.tgz should be renamed froggy.tgz-up. ``` { "files": [ @@ -2790,7 +2790,7 @@ This examples uses [placeholders](#Using-Placeholders). Upload all files whose n ###### Example 14 The following two examples lead to the exact same outcome. -The first one uses [placeholders](#Using-Placeholders), while the second one does not. Both examples download all files from the generic-local repository to be under the my/local/path/ local file-system path, while maintaining the original Artifactory folder hierarchy. Notice the different flat values in the two examples. +The first one uses [Using Placeholders](https://jfrog.com/help/r/jfrog-cli/using-placeholders), while the second one does not. Both examples download all files from the generic-local repository to be under the my/local/path/ local file-system path, while maintaining the original Artifactory folder hierarchy. Notice the different flat values in the two examples. ``` { "files": [ @@ -2852,3 +2852,184 @@ If you're using JFrog CLI on a machine which has no access to the internet, you 1. Create a remote Maven repository in Artifactory and name it **extractors**. When creating the repository, configure it to proxy [https://releases.jfrog.io/artifactory/oss-release-local](https://releases.jfrog.io/artifactory/oss-release-local) 2. Make sure that this Artifactory server is known to JFrog CLI, using the [jfrog c show](https://jfrog.com/help/r/jfrog-cli/showing-the-configured-servers) command. If not, configure it using the [jfrog c add](https://jfrog.com/help/r/jfrog-cli/Adding-and-Editing-Configured-Servers) command. 3. Set the **JFROG\_CLI\_EXTRACTORS_REMOTE** environment variable with the server ID of the Artifactory server you configured, followed by a slash, and then the name of the repository you created. For example **_my-rt-server/extractors_** + +## Transfering Files Between Artofactory Servers + +### Overview +The transfer-files command allows transferring (copying) all the files stored in one Artifactory instance to a different Artifactory instance. The command allows transferring trhe files stored in a single or multiple repositories. The command expects the relevant repository to already exist on the target instance and have the same name and type as the repositories on the source. + +### Limitations +1. Artifacts in remote repositories caches are not transferred. +2. The files transfer process allows transferring files that were created or modified on the source instance after the process started. However, files that were deleted on the source instance after the process started, are not deleted on the target instance by the process. +3. The files transfer process allows transferring files that were created or modified on the source instance after the process started. The custom properties of those files are also updated on the target instance. However, if only the custom properties of those file were modified on the source, but not the files' content, the properties are not modified on the target instance by the process. +4. The source and target repositories should have the same name and type. +5. Since the file are pushed from the source to the target instance, the source instance must have network connection to the target. + +### Before You Begin +1. Ensure that you can login to the UI of both the source and target instances with users that have admin permissions and that you have the connection details (including credentials) to both instances. +2. Ensure that all the repositories on source Artifactory instace which files you'd like to tarnsfer, also exist on the target instance, and have the same name and type on both instances. +3. Ensure that JFrog CLI is installed on a machibe that has network access to both the source and target instances. + +### Running the Transfer Process +#### Step 1 - Set Up the Source Instance for Files Transfer + +To set up the source instance for files transfer, you must install the **data-transfer** user plugin in the primary node of the source instance. This section guides you through the installation steps. + +1. Install JFrog CLI on the primary node machine of the source instance as described [here](https://jfrog.com/help/r/jfrog-cli/installing-the-data-transfer-user-plugin-on-the-source-machine-manually). +2. Configure the connection details of the source Artifactory instance with your admin credentials by running the following command from the terminal. + ``` + jf c add source-server + ``` +3. Ensure that the **JFROG_HOME** environment variable is set and holds the value of JFrog installation directory. It usually points to the **/opt/jfrog** directory. In case the variable isn't set, set its value to point to the correct directory as described in the JFrog Product Directory Structure article. +4. If the source instance has internet access, you can install the **data-transfer** user plugin on the source machine automatically by running the following command from the terminal `jf rt transfer-plugin-install source-server`. If however the source instance has no internet aceess, install the plugin manually as described [here](https://jfrog.com/help/r/jfrog-cli/installing-the-data-transfer-user-plugin-on-the-source-machine-manually). + +#### Step 2 - Push the Files from the Source to the Target Instance + +Install JFrog CLI on any machine that has access to both the source and the target JFrog instances. To do this, follow the steps described [here](https://jfrog.com/help/r/jfrog-cli/installing-jfrog-cli-on-a-machine-with-network-access-to-the-source-and-target-machines). + +Run the following command to start pushing the files from all the repositories in source instance to the target instance. + +``` +jf rt transfer-files source-server target-server +``` + +This command may take a few days to push all the files, depending on your system size and your network speed. While the command is running, It displays the transfer progress visually inside the terminal. + +![transfer-files-progress](https://github.com/jfrog/jfrog-cli/raw/v2/documentation/images/transfer-files-progress.png) + +If you're running the command in the background, you use the following command to view the transfer progress. + +``` +jf rt transfer-files --status +``` + +![transfer-files-status](https://github.com/jfrog/jfrog-cli/raw/v2/documentation/images/transfer-files-status.png) + +In case you do not wish to transfer the files from all repositories, or wish to run the transfer in phases, you can use the `--include-repos` and `--exclude-repos` command options. Run the following command to see the usage of these options. + +``` +jf rt transfer-files -h +``` + +If the traffic between the source and target instance needs to be routed through an HTTPS proxy, refer to [this](https://jfrog.com/help/r/jfrog-cli/routing-the-traffic-from-the-source-to-the-target-through-an-https-proxy) section. + +You can stop the transfer process by hitting on **CTRL+C** if the process is running in the foreground, or by running the following command, if you're running the process in the background. + +``` +jf rt transfer-files --stop +``` + +The process will continue from the point it stopped when you re-run the command. + +While the file transfer is running, monitor the load on your source instance, and if needed, reduce the transfer speed or increase it for better performance. For more information, see the [Controlling the File Transfer Speed](https://jfrog.com/help/r/jfrog-cli/controlling-the-file-transfer-speed) section. + +A path to an errors summary file will be printed at the end of the run, referring to a generated CSV file. Each line on the summary CSV represents an error of a file that failed to to be transferred. On subsequent executions of the `jf rt transfer-files` command, JFrog CLI will attempt to transfer these files again. + +Once the `jf rt transfer-files` command finishes transferring the files, you can run it again to transfer files which were created or modified during the transfer. You can run the command as many times as needed. Subsequent executions of the command will also attempt to transfer files failed to be transferred during previous executions of the command. + +**Note:** +> Read more about how the transfer files works in [this](https://jfrog.com/help/r/jfrog-cli/how-does-files-transfer-work) section. +--- + +## Installing the data-transfer User Plugin on the Source Machine Manually +To install the **data-transfer** user plugin on the source machine manually, follow these steps. +1. Download the following two files from a machine that has internet access. Download **data-transfer.jar** from https://releases.jfrog.io/artifactory/jfrog-releases/data-transfer/[RELEASE]/lib/data-transfer.jar and **dataTransfer.groovy** from https://releases.jfrog.io/artifactory/jfrog-releases/data-transfer/[RELEASE]/dataTransfer.groovy +2. Create a new directory on the primary node machine of the source instance and place the two files you downloaded inside this directory. +3. Install the **data-transfer** user plugin by running the following command from the terminal. Replace the *[plugin files dir]* token with the full path to the directory which includes the plugin files you downloaded. + ``` + jf rt transfer-plugin-install source-server --dir "[plugin files dir]" + ``` + +## Installing JFrog CLI on the Source Instance Machine + +Install JFrog CLI on your source instance by using one of the [#JFrog CLI Installers]. For example: + +```curl -fL https://install-cli.jfrog.io | sh``` + +**Note** + +If the source instance is running as a docker container, and you're not able to install JFrog CLI while inside the container, follow these steps. + +1. Connect to the host machine through the terminal. +2. Download the JFrog CLI executable into the correct directory by running this command: + + ```curl -fL https://getcli.jfrog.io/v2-jf | sh``` +3. Copy the JFrog CLI executable you've just downloaded into the container, by running the following docker command. Make sure to replace *[the container name]* with the name of the container. + + ```docker cp jf [the container name]:/usr/bin/jf``` +4. Connect to the container and run the following command to ensure JFrog CLI is installed: + + ```jf -v``` + +## How Does Files Transfer Work? +### Files Transfer Phases +The `jf rt transfer-files` command pushes the files from the source instance to the target instance as follows: + +- The files are pushed for each repository, one by one in sequence. +- For each repository, the process includes the following three phases: + - **Phase 1** pushes all the files in the repository to the target. + - **Phase 2** pushes files which have been created or modified after phase 1 started running (diffs). + - **Phase 3** attempts to push files which failed to be transferred in earlier phases (Phase 1 or Phase 2) or in previous executions of the command. +- If Phase 1 finished running for a specific repository, and you run the `jf rt transfer-files` command again, only **Phase 2** and **Phase 3** will be triggered. You can run the `jf rt transfer-files` as many times as needed, till you are ready to move your traffic to the target instance permanently. In any subsequent run of the command, **Phase 2** will transfer the newly created and modified files and **Phase 3** will retry transferring files which failed to be transferred in previous phases and also in previous runs of the command. + +**Using Replication** +> To help reduce the time it takes for Phase 2 to run, you may configure Event Based Push Replication for some or all of the local repositories on the source instance. With Replication configured, when files are created or updated on the source repository, they are immediately replicated to the corresponding repository on the target instance. +The replication can be configured at any time. Before, during or after the files transfer process. +--- + +### Files Transfer State +You can run the `jf rt transfer-files` command multiple times. This is needed to allow transferring files which have been created or updated after previous command executions. To achieve this, JFrog CLI stores the current state of the files transfer process in a directory named **transfer** located under the JFrog CLI home directory. You can usually find this directory at this location `~/.jfrog/transfer`. + +JFrog CLI uses the state stored in this directory to avoid repeating transfer actions performed in previous executions of the command. For example, once **Phase 1** is completed for a specific repository, subsequent executions of the command will skip **Phase 1** and run **Phase 2** and **Phase 3** only. + +In case you'd like to ignore the stored state, and restart the files transfer from scratch, you can add the `--ignore-state` option to the `jf rt transfer-files` command. + +## Installing JFrog CLI on a Machine with Network Access to the Source and Target Machines +It is recommended to run the `transfer-files` command from a machine that has network access to the source Artifactory URL. This allows spreading the transfer load on all the Artifactory cluster nodes. This machine should also have network access to the target Artifactory URL. + +Follows these steps to installing JFrog CLI on that machine. + +1. Install JFrog CLI by using one of the [#JFrog CLI Installers]. For example: + + ``` + curl -fL https://install-cli.jfrog.io | sh + ``` + +2. If your source instance is accessible only through an HTTP/HTTPS proxy, set the proxy environment variable as described [#here]. +3. Configure the connection details of the source Artifactory instance with your admin credentials. Run the following command and follow the instructions. + + ``` + jf c add source-server + ``` + +4. Configure the connection details of the target Artifactory instance as follows. + + ``` + jf c add target-server + ``` + +## Controlling the File Transfer Speed +The `jf rt transfer-files` command pushes the binaries from the source instance to the target instance. This transfer can take days, depending on the size of the total data transferred, the network bandwidth between the source and the target instance, and additional factors. + +Since the process is expected to run while the source instance is still being used, monitor the instance to ensure that the transfer does not add too much load to it. Also, you might decide to increase the load for faster a transfer rate, while you monitor the transfer. This section describes how to control the file transfer speed. + +By default, the `jf rt transfer-files` command uses 8 working threads to push files from the source instance to the target instance. Reducing this value will cause slower transfer speed and lower load on the source instance, and increasing it will do the opposite. We therefore recommend increasing it gradually. This value can be changed while the `jf rt transfer-files` command is running. There's no need to stop the process to change the total of working threads. The new value set will be cached by JFrog CLI and also used for subsequent runs from the same machine. To set the value, simply run the following interactive command from a new terminal window on the same machine which runs the `jf rt transfer-files` command. + +``` +jf rt transfer-settings +``` + +**Build-info repositories** +> When transferring files in build-info repositories, JFrog CLI limits the total of working threads to 8. This is done in order to limit the load on the target instance while transferring build-info. +--- + +## Routing the Traffic from the Source to the Target Through an HTTPS Proxy +The `jf rt transfer-files` command pushes the files directly from the source to the target instance over the network. In case the traffic from the source instance needs to be routed through an HTTPS proxy, follow these steps. + +1. Define the proxy details in the source instance UI as described in the [Managing Proxies documentation](https://jfrog.com/help/r/jfrog-platform-administration-documentation/managing-proxies). + +2. When running the `jf rt transfer-files` command, add the `--proxy-key` option to the command, with Proxy Key you configured in the UI as the option value. For example, if the Proxy Key you configured is my-proxy-key, run the command as follows: + + ``` + jf rt transfer-files my-source my-target --proxy-key my-proxy-key + ``` diff --git a/documentation/images/transfer-files-progress.png b/documentation/images/transfer-files-progress.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd3ea2b849be938ddc36b86a337f162de7d8c1f GIT binary patch literal 166347 zcmb@u1z4O*(lCl^@Bo2e!QEX32%6x*ouI+pJp>4r!3pl}?(XjHGPt{QC+D2qJ-c_m z=iYq(&-=_XJ^gl7cUM1!Y$ zUJ06th{%5s5h0Pcvo+qzzv=!uFwme@MrZv=D9#h)e&K1q)B2Kh zHyUqma@-8<(j^4SE)*9dliX174^;TFS2f;D zCsq)mGdhmprcaeGtvE6*BtUowOcYyuL0}y6**l0+vlO*RGzf*BM7dGiLFOVMO(^JZ zE`kWKbnbi+6e)YLqYfFqm{wLMQ`pBc;JPqCRtccNa5_P(U{qeiZJDTNDZX#G0LchU7jK9@iVd1O4iI^6gR^ z^LLbYs5l_e0J^&>htJIL`gQNe@H#wX3A)_SnJ~6syJ;NdCpsbvihgg?;T&`J@LY$q(^guTC_Y)p zD%8dsUutrpbRc$?)K`P(>+E`0zl-h~LnNMvj~*m~Y>Y|~#6@AfF}-LzU$t?*tDX7r zer?J+ZLdFt^%V}THyDM@xK+y@fw%P%3e~5V#n=(0JF;aHmi->eI@m_!eXrpQ!}whyY~$4ZZmOYSZroE8Zro)82< z^w8ROQCA>>j)CyITP#w@zPI?eBq!KDP<`Hn`q--Q;fyB?;lMsPxpyP5pGn|Xq(GUX zA}g3}SbYdD>&eJ;Xg!J0g+(u`7k-D%0kH8l6l8>#eM-bto%pt8ZfmllP5`6wzmmmuxl20 zan1OKS(xEDZ2;gYxl4zP|^@Bt+~248$c*_zxheC z?c=IvL60QWKEZ;>iA&c_TZUgmWF9bjM?2$xrB7^2D%%@h2d&kf?!rIPnY(U(X5>QA zf^6Nkcv^TX(uDRRo`(4f@fwB+DllBMk3^a(8l4t_4pr9bWAa~zIIep(_`l{eTd9(na^puyAZJgVql9)%StXWc{SS)r_ zv+$NS#!T!gH%I;=e=xs#N^uH)3XPq2IHD*0%=F@mauwVH_JWjSMME~PlxKxox|{#K z@RihlGrl1T9ZC(HszHf(Ob2wz=gb zZ}!#CALGM&7QDcg@Rnq+gq32MshXMXFD9mOrYFT~=PH?s4s} zamhB zXoXUi&bd|YL6@*I+f5>@hM>}*F~hKa#3;d^ywW&qf%Pf#J%?-@>?j;D3053O%ug1^ zmN?cbhBc#yEj-;zo&3ulVXlR)ss2G?-?}YActiMN4W-Zqr3W2jk77@Xi;6LeaWpwJ z1Zrn0x7BbpX4O|K(-&^%r7QEx>y4$VuF8gMmcO{qqgLBj4^|acG#UaI8t0LZxE7p$ zkcVCp(BP}Ho#*%^Ko6$3rH`zqlXbEzmG_m8pMj`D6lgM4!pw-ThWn>!dQBTAm&Y|S zd&3yj&-@-t7NeW4Y*I4|4_SpOD(jZ`lpT9OJJy%vDcc6(%+&b``G_ z_bzt`OgAq)RmzZgs1m|i|u@i?zJ};8HGfO(>x~IOLzN^0KL|zup2i!=M zNdJBrnylz=(S$TlSYIiNlE(zb9rgRW-bNKs4gYkos%YOz>hI0TlUtYN`T0>&MtV8< z-v4cP@%nYH?L@)ky^F;P?+S8@pf^gZ#2OhjF2B^x2PQf1l=Y}`-b|`Vrb^OE)jk{* zBwZtaW6Ke@RKl2MHg^NBi)k5*>K7!k45np2$9F8iVR$@=cLL3QQ{vsKlT_vD`= z30);uvYK){EN{uY70k%A$vxH9H06~~Kf85Y`mwQ_d^grgGUc-08#3{4_ZJ-PFgY`> z9^p)G*1PWHDdN%GA+?{}t{GuVRpl>r_v(ApMy5utzQ@KG+)TjOQ2?feo% zNVlY7q47bBM#I%0X0<>YlmPMv0aYc6tkgQS6dSgW7HG^zmFtu&bR^WNv}daU9-fnM zAt-cQ9{EE>O*+`})ujt%Zl+fcVUJ;|oOjj*s}@!D78kh;9SpTK0Tz~dh7B5@Yxr-5MP!%7{v)PV5n_!$eqf?9+gg+1~_|pRZ-RLoD*X`?|QxS zI;*eUk{cE*)Lm%ezl?j)#eImpZ_xb!?p)_u{AGBgmeE@CA@hN_Y0&fL&T|j`39S*} z=3(&?eY-cmv!^SmJL6sbwD8DqxY+Ew<{3*R2?NxP;^Q{g=e0S{0C5;NZ3dXSh8Ma z<%hR8i%UOn>mX+?q8>>S>=I~#WmU#yZhFFfE_bUsZ&mLHTNJTIY9EYcWFTn4WdsOV zNK6Q5a0wFpKtSR{!2VH&fcOac_MhcXkko&*fr5YtG=+fqtBnTu``2GM_ydOi>l->U z00JKT3lseLmIn2Y)=0-`(Elhy@q*t$2rG(w_yGP^G_W%=va1WSX(lFHni3^Vsx>z`Gp69--Q=kv@~+~OyXi` zVP((jB0%~_3tn*fS2YtU$sbJ|%mql*WaLRitnG|QI2oB4nMnaiBqSvKc812hpG3v~ z0tf#RApPRtV8hGA!dLnEtCLEBn8u1)d<&uQyCAjLb~` z4a~vR_AzL~CzSfXzyK`l?0*6Mz4kvL)cz~P-)sL9Le9<DSu-jTio8v_ERWoCZMRXZk1C0+0k3FP->|b0iJvV}=+?4YR3lEx~?+@Imq<`wEZSCybJa2QgDirpC2%VQchw@oE zt$N)C1`@gT)d`l7?dv1I2JJX;m6We2RF*1XVNiQYcM$ID#7>_zKVfo;U5%LyrmX=T;! zBNNdfKj7)wmj_qg4g!ooIVEC#T#VXlYAu(;oIn^(8;-}0iK}Phy1Ai7(mpL`UMRQMf7}CZQ~E9Vt1N3+iz}- zW};^*L7_T z-ACvV_Oz*&GeFLQIQ0GR%utUUhM&w^<}SGOk_?( z-@4(V-Y$W1JCAEwBw0qFYIB|}$g{nU7a`ODk}Bl}c7s@0T8H4ims&H0Tc|iD8If%N zn_P$9+WX()ALd|~UsMPlabHRf1}}kBNxZ3+^VK!w!t>#0v;18WZ&e>H9bDJRrKxdd zFE;$yW2>CpQun|KN^(VaZLTXgHxwo%@DbC6X|v(Vq{ZSJESpIF`MOmjUf#D+_Lh7m zw0-*Tr_KK-_vtwxyrQ;ozA!MV+F`=RFwr4l#Yu6I3OckdJ<9OrFJsdu#AJyMgI^$f z7@uVFZBoaJj*cduwJhArXkETyfpz=(wBW>F{Q49&zqrAiUz@cA8){Pp%p-@IXsL66 zH~zn~!P+E$4W?EbCiGm2>DVxCe0q8#Ga-3c{4KT#%mii58@__Y$**bJBGB0XE4jza z`HT7oTNEdvchAe&M2c1Ei%915y{pxWmn~gk5;2FT(bQ${T~Lp1s94@po4Lt3UKUvdK`IPK%IQ-){jnKh63?CoeBktg?$WE>7R z;r8=R%8SgcxE))Q7SP~BaJ}EZ`4)+uC^wx)>`@u;sC|7QTKpRLFmhou(Lu0bF4KRB zG;39GTc*Q%aTlA!<*$`OzHfRp`I#jyiLuEV5Kuv*sVgSjD(Om?ElrIxy3sUN*>}nY;jn+}gT3O|tdvoy zs=A83*|VAx?>F(L5tFh})9WgBTD1ha((f;jV)m}^6eez8DqPTL)gq;c&Qjj&BFazK zQ1VdmV7Yk@=$$mSoV2$P^IkQ{@wsNW5Tm}#ZQd9u=Y*6`B^ge$$69XeNEF}pVwMl+ zc_t+Y%HHkHa?iQuotTu}Xs@Cz{Qo;y|B@k+Fupc0lgzrqNytd1xmgb zf(&3P|C@3K=f75-u+q9{LVia4>Os?>cw^Vo*){45NT$2$c0V4&-Uck=Sk)emPEIn| zUhE_Ib4Pko>R^uD#Pl}y`L?452?xF{&yR^<6HiGva-YRwCOA!q^0Yi;BQ3Tq4}DeQ zJsL#*vOj=W^Pqm^UtjgWgnc=_37^OH1`ox|s|Db-uQ%n|!zcJuh}<8w5!=gi3pA4& zD_6Yey(Wbl-@Ckfb;XnHxh)^$>C?d2>nB=nNL z;w;8Hbt96SaswV^x}^dr=?alvFYJss!t zOW~6q;_sZ`zM_~2V%K49*z>SA`IA3ejcFMgtzs?5N;G<#q(|k_Lx{A5*<|~H2tSn$ zvV#xP2zGgPpdx}Ux&14HQtW3j7t^#?*hL6VmfT}M1^4xtt8!;6Y^L}E+OaP6uh zH)qoSrnJoPn$!AZ%F}t{iJA5Fl1C1iqH{-Y{@rF4Q1N0c=mEg$j3e<|f?LP~R-AtG zSfW)xh%ZHewDd=%xz5wAnfgvzy3yW9rd%KPicym?}l_!V#OkKV~=py144# z&TeC9@Db2+!UHQMVnCy=!+W>7J+|6%R_>~(?!4c^cjmP_b@6=Py!d^!QJLp#8*{VS zc5yP0bmhjS`MQCzy1{7g8<lv=wAm-K{#B)yx#qrcE{J zbDiuHbs?cWDIY7F3{)J=_hJa-nwk(iUj2-?05~<~C~olt4C}JVl#JMuS#!2h)x1sQ zb6rh#5!}ME-*BCUp4`#p9Y$Cxo?l)%xlzvb_~RJm=0QttIO)j}h5c_P@BgS-B9b!e z`!<$8a;sfW^VJe?)u|k9#*})#Mta8nV9p~|qN4$H99UcKz&hWO-;SR8`LMk<8YZ}E zg1Dgku*CRPM|rJeV56{Sij{gq7aI_(^GMowET#Jx-UQabwTDHJIj3)|t#(GFsZe`1 zIv}%?TqjE`+=`-&2M!BAu$!hMOi5#!`!jV~VP#sU-3-pj7jjnX58%N)GzGI{bHk_MIGWVY3TP6G~`S!4m z2;f+~GmZ?>o@7TlMVn5bue$DkOMNNBLdb2XeoL4RKqcYV5!brN=O8r8z4t7x5pFbV z{?TBiOi{~qZ8UpmmSYuhHe13T7g+h}e0GSco~L74WB;1{E#XDi>;%)}l*0ze2m3Q; zIK!UL&-eE$LV{$5!+g6Y0=3kWYL#a0iiYUAt6wygajRzoSRX6o#Jz&cm(OUSn{~&p zcc#2Dj$T}z{F+bjq7=i{cJ)Xk16PZ~-10h4M2SNh#!28m>IxcL@Yr9GV?c@ZhXnEu9!T36hk%x)-+>1kqLNTn!oA0>)PZ2xi2UXkK9`T z1ifDJ(c>eP72-#f7yBOo2`gyRS168qS#nkOczusSH9+5MJ{~lzvlg@|tb^Zjx3tN& z;merS_8?pyX{++&Wy*qWgs&9!=Y^w+mCdA?#ew{LR`K(kp87A)3d8O7_d&P3P+hv# z$Fiuf{FFgzk^+Y{k56tIu2Mey{Tp+ni$}jSMcL;^Ei-EKY_JidRNbuLLE%njD?a3c zYu~eqm%BYlb*zqm6~4XJJoJ?vqwg)M(~pLTH*XG~CT{koye^-vYX#;WQeqD{P}|!} z%c06OX#<#$Er)*?n-%Yqx0Lqd5hb{7z!ad{E5@js$f_vQx(l!_GNL8yhz^d=?X1{U zMNu-K&nJj|NF96Gk+E89BmPBGslRCYfKm8!M?cu5l^vJrbJvTk>DiF-+naq`zw4m`V<@ve6VyLZ*Q19+^r&a1j~rh{1UdAY;Z%fd+- zH1Rqc^o36}w9NH_2dI}`VvD(o4?#6An^$O8Ef>!~XC@$*SCc)#E;sxZ4@qk>>ZokC%fqu%Yvn0pHX_mZppRffaIZFKW5#AjjE0DWf zTz;Y|=YDDXiz=RiQzx@R3%{sxthXaq^@LL8o%bhIP=22(+G|#Fjj0VlERruR;p7$LiC{kpyYz{s!|yi}08LXv@pEMZqkdRQhPh z?kF6?C@Knq;XdDTWTsSE#aPh90+V${o9$PBcvt+`VeSXo#>?EQS*I%#4*cDx;2Oo; zYb?u`&gl~jyjTP5l+sRh)FuqnB~a)fqctY1XEXan)rT#+zzjROl~O*dHkMTTNV@BK zw43U9LW#vkyn#FJt0X(l(>YKbUEgqW-AU%z6LXEsi$wD2IFK{?F7w2^%#v#RGwJG0 zdxJjTZ&~J{4Q<+}RfLl93{ZB;V^(9tS+%XLiKs2=gyqQ3w6~ELIii=nm7TK~X<#d< z4;P+8HYrMMQZ`A5Vn>dJ^=x~1Aj_1FY7DHwZP?KgR22v zHJFouCf>~GBW+2X?|8P;hjhh=?ZpD&G=DgK8a_5oXkreGWaHO=mdOG;0@x3R`g<_A z>8z_TcM(lex9v~z4t~_o8sTK&8bgyHe;JP%dmRg>+72$ z$DcA8`eFUyvvWRP)TdCZ3xe$tm!+HWQ?D;tr|5KNr!1)xLOVd$#q_C77BsBA7PM}h z#ozJ{3L%OD(-h4^&ne(L3o33vAHkLg(I~C7VqsWcg({5m3|Mt7_U0C4@_6<%J6Q~6JOp#^46}W;mh3QV@k+KZ7XN?+Sq3g_fv8prJ_`bs}1= z2r9JM<^9ZHw1Z5dhGJR|OINXYh1pF=)c2~{canhx14d)Ss8*ctp&BZfC>Masa#5?^ zO`c(akqaxLox_6djVVvAlSwV&{2P%Ap53cWqY;i$Vr$}y@_ zTq$6=XFE4A>0wtP5bY-T&Y=urp5S*i)VLYiM&(uWO=Xouw}rb7E881Nz|w2q3VE~{ zn+s>rsxRI+PDj;{4`*~lSbsp^YEIG zUiW4m)3QRTa@ubJ*4&5?l8q6LNTvvIXcPZfa2lZ6hZO(PmhZ~FaPoj~wo&$5+CVsz z0l=o#O(M#cZpW)4eBwMZj8m1BGIxUNSm)#M)_T3tGtw3Ku*j*$mCc5Ylg*qIB`MOm z)yfHh_^7;pU7J_1IS3XvT}+GwMXuYkIP=Ee1g@@Kt1c5r6TJJ`6Fi+D<6Dtd&Z0iH z5fZs%F4Prl*dy;|jmD^bRdm%!xp|3In2BB=eOy}J=c?GJG;!ITVhY&F;(1$Y3z;+U z+)6}-+6C(H4Kwj@eCPV9Xmnz$o2P1jroKl-LJV$I$eCJR&9O!)09u5NGCT5>6=(Oc z9mz>hZ8SPO4zL%qbm!8+wv}=S(d51H;vqPsGm{+B{UE#xcgy?4`nGO@xmTumvh79GD}1JFS<$|kRWkZc zn-nXbHlIg_cYU%_Ns*C9)1(TbbASP*r-1<7W%xucbDwZ{ik{WWj&mi0jWU9YhxMSi zJfagDRgL%b#tg4&u#xe(>vcS+#>^dygUBND5|M^|=WBz6RUTO^#FV7(TbwuNU^y8cpF9o}DlKe^zaRD&g{VmWhi zuAcRk9m2tb&#pMtA@v4~9?Kk!3B%eyrknxJqA=#T!D%X76ciNWk>0c!JgG?^!{9Z< z#_AF&qYVdGBv3iOCr1|xii_pSR9N)4S5-F}z=v_EI*he*6@vJ;!=y$M-@{7T<=IJ* zIo958Ev10nL}Un4Osqex9`68ywsjat2o~9h-RgE0V24xJ;`EW_JGp`oN~Qq}NRX-i z3amaa4~I9YtW7wfYzhzyY_i}HP`7M*%VijBct-juu_1rTx9NsC&k0z?sul25Tamh` zkzIDqT|wKtYEt!@5*id_)70UGpVd7pRO}iBQksFi&?`cvkMl~+#X;9k)e}P^vUl7Z z-bt6X`b4~rs|>qe{zsGLzwIg#VHk0G8!i)Zaq5E{xIG-rmc5gZLkfP>0HL2-IU@L7l za!chB!g;cM5=}~oO&W*EwdX^+HtPkW$xSsK*w5DJiIy|ke_^}9!=Wp(XWsk0@?9n9 zQu#VQl*h(#=Y^2P+IWhv{zTtewu!jsz_oOKUfO+zh~qh3ERrrLhklUlRb2<(#8sR2 z@xM8kMnw3EP6>TW>sW2 z85pLmf;+NnV>DUwd|CILQkW&YI{)FhB+2yBOUe5rh!fm)ZPUhRJ*KlLrkTPIHn{RR zzMdYXFkL(ayQQ`G`WCr2d5XOy?qj*HJeE&Yyl}m)df2OOtQ{DdsvO0+P-rsA?^xk` zDNS+`&@E{ojRkKusueWgjfHrUhpvQo&Ejok^RFO7g8R7AKx&)}fsHj|JM{^N?CqtA zY@U5kwUu{?;!$r?XiYNKFUO%3Ky~W3B6H!?P#?@^iXs#e4rYp_zMFqc442-+`t;pz z2JA4(v8MuQ!$rl>dEm?PS-~L}?aStvihkcIrseB&{NRW4KYc`$gPTerKG&+x z7n#C@Y!tmx^Q10Z)KE>02_937P*Lz2k!%9z@iw`2U2NkF+j@ZrZ-{qwFx{Wp`E$Wh zyAM>JPCvfQgCmKar+r@PJDwmMBl$?apaitqki$V}?-j6~?7^CO^dt`z|9qO&0OEmz zZhpOs^TOS^P0adJg{wgJ?hPLSMNIpUNTVY0(arL4(m4EY`LSIPxFc=3h^RQ{Jnh1> zc;qLVQX`OFZCT`^z%LBtvSv8yO8A&LaR7ID$QRm2Z%6&3*#xw8W_nUjGVh;?Yc9%e zmuPyj(RPyhaCSHiuE;m%8g&bp_o0g&xE}IUngTv?%M;i$*Q7;_(wr26BS44HL?%-~ z4VMvpaNiG#6jgFMZ0MyP-biqb{Fu)uw{F-LUkpxCW`y6WBGB$2IqM9EkcGs>MGC zyg}y^+IV)=z0w;bG`a5Nb~VBT`wsx(A{jxQgi1|L&gno(dW13iC~HfzZ}Chk6?BLC?VX7#kg_&PYq`DvVG_vv%z zIFrq7vIdz;Q+ko*Wh(Os`fs@s(S6#uu_QGrjb)g0FB%*Vdgik??S4zB{4F(r*#pXe zchgEm1!vj&<*CYIp7s3UsWaEuo*dXK(&%&)Nfv^`&~f)g{B&HXiqeA}y%>=gMb!L< zcq)Tt&6xeDfCOV)NJB$I6&ultv6&eyEEMGa(Gf*W$DP{Ky1~_$=IOXtk>#zLz$K1{ z1BUrqfC^eOEU|XiLI7}D#JXJqx4h=Jn_chi?WM~ka`tCCzGlF&XyTVMZ&#%RQ~Qi&8ScmUzTLsn;pRyo}ke7t&2PHu$tL}?z^tKx2HkA zWC3f?sdG@}5)zY-cb&w~Le@=ZaD;qL(r^QIV~3K_Sy|*8XtB7AT9Ps{GTg*Rlx-5w z;|c#xn~wkEs+@BgdirQYb54u7v|^T)M7CV%EUX>5Ttyt&+<8Sin(l*)8b)HvC1u$I z&f|1HiGyA)^b(@~WTFhD(7n(`sW`?M;fi*>@Y_ykuQ1VdA9n2M9^o!-;sb4;e_w*k zX_K4dWhG^0v6z^c^Jtzt7xLiyKteGwF>d0-w-Cf{Un}BzNWbA!zMV_^*|28NQI_A) z3)ejbON*26+xTKkmc^PJMU zfuH{VS0G|%4${9+f;zolI34$u5;=NQalJd2nj%RxJU3VqqE6D|d8`ITB(c3EB)8Bm zKLG_L`-!-cTPwb)FeM0|obY^P3V~ReIA1t}^)LL-h@9^xm;`Owt*cB-@=qbU&uH5b z)C75hy3Hey4q7&VnMMfW!oZcUKt_Gb&ffj>TJb_T67;m=W2?Ismpf3LqK;0=8BxBj zNYlcj&eGhRBvbQcBtLEvP#ORK1{?pEO;K}EUcv&HTHtYvP)j>0OdN;LvFdZd(H09V+LkC^B#EggbULlg;&;Ma z8TFsPrOJRZV&4h#>kf$McJ!8~o&>Wh#DWj5k2xWF%l>S;S+J9)ZeBR9qE5>`-|Il8 zQ_JHYmEE~QiW-cRnB7@Ga&#G&m#;9&2HP72rlzMETCRpA`e{s+xSe@GG7LElWDj|J zbMKJuJ-09+o07;$-n?EV!haPmVYv0wb*}H)gm$eoHu&~tB1HsYO(yy-tHfZw!pLD< z40pUlyKxs3r%U9Bm^bD6V+s>MMgiRXo0bwv>8pTUrztNlBqwn7`plcW^{nTu12}m- zjFK)1`Hv-f^}g-oCIpRfc|%0@`KRLRt8~{q?B_w43tjnqmg>+76qDtn#X^nA-L=-+ z3;4(N=N9}CDi}!OGiU6dg6aJ}J9L-0su(9Yo`hhgz5jq^#MsvcHAMXAF}n@nwTj@o zc7yWR@|hoBVMXNZK`j;C@mKvFjQXS;XV z?)=e*7lRNhBO|gHrw8fLRj(3SPRSFvo4=W%on&wC+nt3uc;U4TIz95Z)-nlMojIqQ zFeHmnji!nxUMo)wo&-VYMEJ(FcB2|uATPOWhFvzUK8@6U2WRVlZ+X5deS37K<2yQ+ z3JLZ;e*q0soWBQ~P!qj!LoJ^$w9v z0}~$KWeTp5Ik#~f5_1m-VML4zd5#5Ll#fvS7kU1Fpyd1$+u~uTV`C(Ocj=B3MMP`o+M~_*SYIs%gP2Q6HR(#XGd3|FwHG*Q zk!JZo2jYHy(+KtJLI7y1wE0>C<~TtVeDJ@?oOX?q&WyCr?W<(+JeqscjFiOrPjT_a z^%u+XofB|F|DosGXtXi0qS{b8VhbHyK4%^QTfIVo#kfgwk}!b#p|aoC|Ncpu|52M9 z_qe?3aceBDOkCjQHEgqV6Q`6(=JZ<--ChppaYOoU9c3RRq#2R%-lK)#tECvdb!1<` z0Zv#=f=E?sdgOUd>{#@Me{@Q`7!gL<0oI~}Gnlo?-*1rBvuMD$=;d;dYqCw zV-7cdDJV}BFhAP4$tW})`?eu%(7dU9-J~S!_@Du-#qas20Ra9l93(be=~h&Xa9}ar zwu>3A4lO#Pd1k3U_4f4+j_fBA{G{Bp(oQ7~XU%;NQ`&0CS%!y=A1xELOe0Y1Y(`5U zg(Nhx@3`J=uZUAHBVYmVu=sU*D)pr?n_kpp?o+UD5g@Oce##6vig!G=KbG^;dq(x} z%VkWnc)zzh-AfdvL{L zp=!9DEX{+JD=(!@akTu1dc<$@eV}l^j|tE@@=+@1@X|11kBb$fTQ6O;Si{I;aPRC| zL04DKdD#*7={&BLf2H8fNno1@nt-TDiYsMyPEIh-ln@&KsgPhzMalV*wRhqO?*aY% z-E^r}45#&qh4$xHwMnOVopFNnxqyqy4-WgdI|}#TUT?ZAGXTJjx{$7x$@BN^ZCBaF zO0~0qUGJIrDAV%}g3a6BLM2Pf_iM*z;moN2u)jNgE$F%x4I{#z3wj!aMh${bNQ%^Z z6Y>~BZfnuJ=JB5NblfDM8s*;=+O^COwZ+qNw_S$YUD6p&k0K&BWI)6B-)a`Tomt8? zv$#xJHbaaMK6@0IY5@Ng60dAfI1Y<)OVP@TXnJ~D-b6L`?8NRa)9M<-`}<)%skzvg z1V^@J{`xK?EwzqxRL|pmOR|itM7K3%j$KeN)y&MS>*<8(6uU&H zc>!UGftL1T9ysa81MU^CEa#fff}&{KaSeWT0{i&ebSZjLjjxaDnFa#}W=P$YwMsQizEia~u9s458WeuL zP{2&rgiI|9)aiWuzi;015g*_Ojc?G`3V_{h0%9;@=O+CdAk6kU0t1k$LZWrtJ=h`%STG(n*s%e)Y%#SRG(I|Xr`7XK7u5G z3Svev2qP$-4BE18NZGd&-2g3Cy}07L$_t$p6M_LOIsVW6_XCg(_B$ilbfry^CH33* zo8Qp@wn#JAL=Yv-IgA7PWgiATSiL4K# ziZ?I|jn39DoHk#Ie?@PHn{5h=tRHlXU!RD1X?RRaOTEbBZ(B5i^CBZ!7oP0NdY2k;{?AukiKyyQSBm*zlSE> zETM3~-N}5lo=JWfcUtbO(0rbci zPMUAN^hZ)SY{#2S;F%-|6I>1*pEO;dJ{>!^X4cef!ry0SWsT(mu4r5to0w34Zqe6f zXJ=o6y-M*;$4huu9z)PNrK)husdfW2>?R`w1H;4FPY*YfHI|E8cNTMH?M)5YBL`l4 zQo5|i=|*LxXQ!QLik6ne%i-fU^`o9Y?Ck79uQS9#LV4j;!Ais8m%@P-&xc(m@4FB) zar(dw`{VkZfrpHfs+^nvBG)a9`KNw4uSlzU5RR#eni};^$9iYr-gcsO&i=kx{SQUJ zz3VF{qJ$f^=m)D6v{|0rr+%u`tb@{49n|tp6Tt`dJFVS=p3G!6vd%fnUs*>tz3#hn zyzwU?%4a8zAZw7Q@4s%Zl!2M7gaMiN4^5;E z5pqO&4Qn3hE74iH;jX-Xf_^*7-*v_yLEru3D28l2?CfQ$h_p_V3YscRD>qj8>{ zB#~7xOOefNwn-en#ChN0y6t7hk@hI}n&u{p0|EEc3~FUUj_R>DOZI3_t1nNfujnmJ zP0K^$-x9Dtc45hh!t~gsvA_@6-R;SFf7E?gm^Easan&ptP3DVhxhl5aTaM*~=X?QQ zfvvsV3rl@EH0koKaRTiZmQs4{`JZT3wJoRL+c0y%ukHIoJ9}Rh>h`yNc}mKWP5ww= zGXyzBYXi;;a3m5*4m1-KX+AL%G;=*DuEiH_T^;j{B9L z4o(gCfl^>yM+Na4r)mq)#Haf#{XguzWmH_-wk?bW2?>x8+}(mExI=*89vl+f-Q9u& z5AG1$-CYZJcX#(f-(sJ;_mOvYyZgR-zdv8QY1L9xV^vXWt~uuzqmSPE0+cutwzb@Q zN6*cHvf{0gyMj@#mwyxto}NU2*wF{-Z;~ZTO~R;E7R*;}WKtJ}4M{CtIxd1*2pnJw)1THN%4=NpD#>rJ^f^plOg0*c7!JT2@83dk_ zH&5YW`oZnTIyY|2_d{td1}oQPr6G$hu&yhpw81AV8?nyuCFC1na4cT)zoR?6n+;-);mxjmY^ zhAPk-t{z8U9=qMNkb%d=uu8gg7ukQRj->>xT%~R<>>df8#7-Y4-zV# zLO-zs2~|kP+zTx0v}|_6>r)Ux4#Cq6h&UWfNUL5equ;{~toTiUYk8@FwbD21kb#C) z+2C?*e%prZ&Sz(5$E19HHE)pvcog&wHfqwlJ>4zmv^*SI2!H*6oSBt1O7DJ(NMaa! zJSy#eh8n+ESyvaoHJnQSVa0k&iLOAYBxcqc2yvRTEKjH4VUH#Fxx<~EGz-^t9448Y zk#xb%>C?*+kHwx(1N^P>*%Imb`PAohhUZ&@m5!&{>#h@o2JM>=qmSrAd;?y2`IfMn zLtpy8@7u@Q(NI%Q>~)V(rIxsE(p(H$xXT~aq@{UQo6ZvN16`YoE_(M-Hhiro5dybQ z{>TI|{9{0WBCA^%NeUS)$JNn7YEY2k$YpsG3-O#8C;8Xd5iZR~apB>4{jhoPp<-OmpYBXLVo@cBk zKk)GF?;SSMe7>8Sj89Dh>KMOmK*6~XPyMFnEi=cUfZB1%I6 z7FdeKHw178)(9_--|FdS%Kzk4(l=i$)1i>;OXb54OH?x) zz_bb*b$@!e-t|VLORF-O#^x{P!l$u}W!;jfSJHGMv$MCyzPnu~c>0X{&J{?ZdU%Gu z^lewWKRD~)4Na-Z$!S-XG#qhYRTgmAAI$L6x7?Qx^b|n-WGB37gCihC8e)!(rcuI{ z#NYm^tGMKPE*Vc{cXxI8QA1bd%8~1gBh~dxwCYFMLX}CZtWva}pC9ClBlCq?Su^Tb zkx*PlD2HX2V{WWgQxzhy4nRUfzqjPuEJ|V9IxrxivP!s1@4AY3aWO6}!X9Z^gUTZ{ zB$#vLa`RG@W5Id9Xv5y$=ZyDe1)7?cmbrvQe;-JXe@mE6?kh-~84VV=FN4m_lq9Ul zWFHqy>vvpejQ%EIxq&5^Pl5Sc=JMS2ZG}f9v~=*bfIvb9ig3cR7tXx|C-QRP@~{^g zc|SnR9^{47PKs42P;&dZS$j(2M*!{|%B%32AP&xo=cH`tO$u81*GJzJJT9$t@KnaD!+O~{0yX|yka@$8+vo8o|naFbxX}Mzxpui z3zG`t+AML+>Xm<(yy(VDE(o>;kKL%)2d-$ahX^fB&x&0VH?w~DpaJ7qJ)YiCMEX|v zhutUNV#(dj%(wS^55?q7=!x2OJa>BCsu*HiOKzkKk<_ zAeBAN0pYt07~1FoNVc$cD3E8?KRw>jt}m>>ym44^%6U`U@U;zUHHyk7iR2499yd2P zlS#qLSBm>L5AJIcC9#^$RGV8{eMg)9v4G-ZkUtjp{%+vIaPD9T+3|J1)?@hqOh4o# zD!D`&suY_S8^n})eM3VCd1{4bLPA1-kN*cIrVSY&V{Y!tH338-`)ki$AI{f{4$tDw zIDnRqfBgUeaM}HI4Z&=Q^uriKbFR}G4wnzCi5c%YnkzP5ArJC2@ZrZ+Y#h1Noz-rK z>-W_bd^s{cmAwolH!j)zweaf|wR(!dy^bHM1yy>?4*9FoHV$=Hk$Dx9IUSQ_5_vB+ z7W2K&zaiZ8fIYz(_=w|U_ocZ8Vi&96y${~VOR17!h)SpD{kK$@;z=SAkzD59> zu526K&_eM_pPql@!Vw7bziEo}xa{;mHfC^>yl?heW<3E5?_3{^;P^SV$UGJG;oW~A zo9N!=b;CdT1}}SZC(Pxs439;zlsagZoE}e-EzM>dyX^gGOWmptS7yIxUVNPVT_lJ( zL>-?V4PD|FiT}?oHTj#S&y%myn-A+!mkVlhIckC(n1QAEEkmSue}Z6I%Y*xr=F95W zxkU4NDq+kD(@0R}zu$8nt za%i|+PL`Wo9n2bkro*7uG_8CBtYxt5n#%3=zsyw_Ak(T=envV4?*M%|{8%mbI^344 zIg>!>NCLMD*|ox^d`o>5_mJo{K;L5G4$Mt|X2aOwj$S9slDo$~nvx!g;n9U|V~<|2 zd`~2HAE~RYJa?6%1KzcqoJ}O{zU%!2|Lsk$PfRmazx8e*Cx-lO=R0t7?OL`r%#o_^ z$nRZ&uUzoJhQPI;r%v)*LBDyo;z34m>b1#`jO>Bgr^T;N$Cg?O`!75E|7_4WaBa^B zls7rP>TOlUs-z(?7WArieOT)-1Mlq~WoGsrZtNCjT~UeWiCx@56Bn3kF?zrb&3|9B z6{4iGp#Sk|COW;&t*y@OZp&ShYz8OO)5ycE0WYR2(V|)O>B{0s7${)hfD(D!>PH>A z(3D2HLvTW>HD!TRpBEsY<$5&$yZAV3RpsD1^?9*sdT#D##oor0Q6nJye*-#H%F2e= z2#V|wmq!i91Gfh_li$Qmby zs2j>lg%Sys42i}LHJ=KD{!S?h&jpM}Bqun7_Mfdw7{p+Hxy|$t2>bCgR;J`GmDD(y z9m#i@6Bq}_I*ZL?i4F;Q2uaZ=kf5LHMIY2k9?me!X)@1<*FE;goF<6 zI6o}aMTo&n?x%RLm1WV6q_w<(Jae6D*K}PCZWf%`pSR{U)Y_jY`rymxj&85&^I)cjbqU`YG^~4p)pci=A8!s z5jkf`tRq-C?I+t(;a1X=oV66Pa zmoH!L2dCK;2%tX|Sn^$bj!hqU7UrGS6C|OrI_Uc? zxT)DuD7q>ymk7FD+(52PpZ3X?wahiq0tOM)>dZBi&|VE7!49_HD?kJ?ApQ5PPp-v$ z-di)oJ$ZeDr~N}7n&i&m(%Di!GyhNV3;ylpNOU6>LCwgiY6^nlANondbZ`aqKxiT* z&4Z+72fb?6(BAFa<1Px(S>(enY_=G0rfFc57{YA%dD|<(m*PfvH8o1p;VrtKzLYT* z+re3{<;{f^EMU9Zt{CPKe@?gbJPmdbZk&%&#llD%HR!ch%*ULFTgd87aU6x3_oyakq%vX&1`BQs# zIf2<^Co@v&7l39(uw%}Yk5QW99^ZzsnmdTzhxh@xbu|ulHP3INBL@l#U-tQ&FMQoxRh*ub)B_UcXpLKwZANvZgG7f4}}@LrAamvy*i&FItz-g6(9$ zRbojkmY%OjgNH+5Tl5$3NdsV)IKR0hwHwmQVf0rpzR?aIAm;{Br3pi!?YZr`7!x9 z950yx%y=Nv+Ff*5&T=_!ie;lI1K$8~*Qro)okib4>lfbpC7#hxoMZQMH%nvugyGr1 zyT@n9vf6x6Y;$w-Vn!$I8D1Uq$F#Yu!;mD4rFbW1?I=iV#|*x;dks(}A9rgCcK1MC z;_t`Lv<LB@iuot)%ma#diN{_9B6pRjXPxW_{PV_ic(7EI`3B$fz zSA=RN1eD0-2WNLH_spZqh%aL{q{TJqKS}N3Q z+QW;sVv>zFT8BsWfh`R4?w*Jv*XHmN;caKX)6Z>cYNLfhBndTPv~3(gwh z$J?=rz#K~Tibv1)3^ZxmEqU+n_L{%!b31AFE8zmh)%L=WjqteT>8>T@T*=^c$>mtq z$SBWvEF+A^7@=?z638k%fWFC2{eCeC($|d@O(f?KMfbDF)Dbi#^=~ShNj5|26e*7F zJMt5i#X++Q@o&!J&CjyIZ97n$ckSTFaVjpFyYDs0=&K1N2e4Re&n) zcB-aX4`u@J6^vvjt7$*0R}T168jJ&ci9l%1{r&yG z60eGs{IzrN4x-kLw=s5qb~d>)(EkV?Xfa5#dS>Sa11k;BNeV!!BCrA~%FBbzG+j@H z0I$ai{lQps_K5wi4qeN7`qjq@<=V^t0n*A;s(%@8lluO*4w9 zU4&Q`p*>2zNY(+EDVzAwlHKZxd%qYXHs_;joY+vZ03bsZdyCa2eRl?>>Ik;YzpstB z*MRJ!?MuVTksyubyl8}j=6BxqZ|HauChl%#g!yBud@BlcwgYWht!V$)QU6ptZ5o8?w8II5_&N~;@$fxxR^3MO=BpO2KB(2uVhCKvXMGKNq-j2q@Y?| zsSu>%rU1SoJUivykpCG3J;wa^(GUysAx?eDIaW50xfg61%w`0@zwB7~mF6jp?^ z7{!Uu4s~JBR_r!AK#Uobe3NmIjYwC^*R1Qm8}^K0US!d`^-iFwY3WQf_GEJ8;tPbvGZRS7U z9?prB;t;jp-rnwS)#FBGK(>a}YG!G&{JO_Ht)AhaHrME3_lmjHV!1ias{uFn4rmTy zd37~vSXq_1=DArylq5%>^58<4VVn$rrta9&*uJb3%LC?007ThP4`*BlU}E(E8xNSf z>?lb-ef}96!-Lu0T@hXlTRJufXzT39a1^1+hLqjt=47eExxJ? zAW*tq%8Fv8c{h;?=q7HmV)>-Qd2Tj&jJamAk<(xQ{ZeWY-VdXrKFV2n{e^1@0dw%e zo`6f(;b{-e`HEm(ue3->zk8EV18HgUCEVE$I{a}EyQ329$qzlCd`RYYkFaAUWa=aD zp8L*oW_YdX8kzcDsD9<%4E)K^nugD-As;@%rlRa4u=Xu0{$*lfKih9zTS z8}L$V9zd!EpMgUwPhx|z$^OTOyWJ@@3$h{K`AM`pRbvyA-F8I!D6hQ5#l;v6#V=p_ zR=y2onl!_ni@9>+vJF7CKf`{=y&M)bKy?xCbUi9U5Q3?M*Lb*_lS=nt>u9FThpnJM zlP&TXXy!^ho%23rAotq8SDSx*%aNgx=#+?KUh8$!6>o=wQ`8pSm|~t&ZP%W|yPXq? zVWL3+c%S)8EjZX68Uq1FdJM>?=_`27nPX#O#(>37TR~D_w^p~YGTnym1}FffqgAY( zJm8iJ$+bW$kNo^VD^&G5dQjm?7!CXhqEz$79e;lA^Roa1aKOkz&iMO9>i!PFbQBsi z9~|`ebnwrwRw%{D(yUO6yA`wCWh`6WJ$MQ#vhG=JDKfbMpdJiZ&sEGXaYR(<-8 zp-JctfNNtv$;5TD=l%R(scC330Fj1rqHyrxLY+KpmbLK03q>g)fU-j9atcGa}^>fU1$ymUGrWW}p1cD!L@MD}-H zj;?U(jdx{lP5vNv{^(!P_&8`5iaWF^`U}VwnXjrGfa0Gg?xn$j+no#XdesdE68rdg zNN~d;v&MvDZn7ip-}yVi27t+F=ypSxiT@ut_@56tG0f7kRd^ru-j3FE;VT zDJCgEw|a$(uQvBw#!AwrVhRkgB~z>{(X=3Dg`Jp9q74#$-Olk z%1*NA;(@o3sQef|1Bad~;>_kl&-V5}eG`*oY=w#S3?1B;1RwjwV$w3raHL85k(e=6 z4$DF#3Al@I9KhcUq?f6vhFCuNC;?YXIO00C0+#!$?5`04E$oQ$w-s&$6)=jQ%V3@Cd=t{tnnO+ z`q#P7?ZwaUA>BQsBqg&dD?j$b#gbS>19SKc(0*Lq{(nJn`HeAC5%z$+o^$%T8c`n&w=x6kS`=!>H2Og;Y zD=L2NEo1}#oZ9RsHRK6dNgbLvQy6z3`5sH*cG>8eDpE6>;`>|s?T?G-bxIaqsXvGf z9_F4dQe$0H;&C`qpR2J*L$UU?M(t_estB+5j$St&fQW%R@)xVt7 ze_zVQj_r2yVeZ)Bv0qK;2p8;Jx#6o>A++z`W_B7 z5#HTB$}t;Fx65b+C8ay(`H5@i<~}pRpV4uIS$3C$N20>2`M5ldsRLTgnm@$*6BdzZ zenKFG|MLUa8D=iZ6640k+WNv^5bO!JX})y2$;{F z|NKZBeDm4ZgnO>aL`iM`?VTVLDc@gse0{Ux!i@-@@ox@Bf%fvn>??);*K_!nQ~FO{ z@*yI~)Xocd7E1kvZ}aEhxC|xDk`-O-{a-w-Klvb9QodDlM96ZE|JFHm3V60JDpQud z`fq(oWjMt523nY&y?-{&F}vDr;G?dy*sK#AuNde=jr;N zT-$#+nD0Fd^?250r|_WRF$ zViMtF_0BLxf8ki+#&nMJ253l(U-(A&qSElF3&zbX)*~&b*ahnu#JxufV z*GG##yk-*qJ$WC|hEmdUt5OG`Whg-3sQt@6)ccN92i`@f0q8`Q17Pq2oj!0v-g-dW z+&R$SbJ{f4>@1;jOhZNn7r4C#r-V2hC{xr5M__We{pmIT*U8ag z04PP|6ck7kSuLhs5L)w~__-)313=mxswG4Z1;h`EKvymXDDMqah_1*_JouQ9{AUQB zYof#i$ibe3U>Lqr(ugoPVZLxzs5Hl)Js@Zj!p}UAGF+k?>t1hANK+vwQ%F1DjvH3= zLZ{fg4w7*53aI4qEgeLy<;o`}r@_=h9uAmqA$G-H%fj1eq|-5l7gx35RazPnaNQgh zL>$numrE&a5d2=yc{!qbe#Ka4TPj#7@PkjZT5R-bV>$iKFOLrH@zJLcStR+|ru2$( zDdc+eo6GaWv@}FbvsA+K7+~@HcJdvL@zoSuJ44U9d`B&$XBqEf2H#(u4dyp1=MsvF zinlzcfUJcfF;_-r6Hd?&!HXzlAO$fIVYyUY%rT&rkyQPsqK(p=ZeX5=-E?V{A%pkKz{ zx4BDYGeio^%p-194SrQh{lfs(zG;nn{eaxP(d2S12HYykZXPp;Xyb4qFLFqb2R&0y zA8;Q=>WhkrdD(b^gvIoU{)U5iX?o;8YGguupfI_V>EwF_>HP>-L*eG}VsOxN7XMD? zGuvN3cX|R}#(5m%pc7Ao(+8tkk?!hIILy2C9O=J$G5&lFH@aS3S3oz=AJQUm)1|l_ zP|-x55A#Zo5pE&O2fFPQ#8=(c1x&53g)z~NbX8za21v=71b8H2s> zqY=A-1_``=o%RO%_xgcP9bu)p2j1b0pFD4X15tC=+91dc6&NmE-5rKzbs2T__c*NP zQGlpK-Xr7$X#R$n5X@r!_U_hnanE**{h4)w4YS^v)EyBY*B%NEubnzBkAL^vQ|D;t zJG*$f=k?Rs_gx*KwFJx3)5k^vYZ~QKziTmbdu69+9}LOp*P0%Z{8ylGLW0ZpA9Sa{ z-(RKh5^>$T?V`57Xx|4mF*o;cWN}OCHf+XM{zckl1+)qpyU@#~gh1Z}Zh_2trj*{b#wmxtqH+&T2NH$tMFOhRwR9Oh6C?D|a>-^q2? ze%PIlAsYe8^`rfOMYq&>whXFUOiMPE$ozh$Katn`C4YV*a-rd3nWO)>1S5hy)SbZQ;AF zjlP+S8B^pbUKUJxmtgFUtAxBR<=FgWn5w#Wd1c8^_S>RMGkg1aH|ae$$S&fior~Ud zLV5M9=oR%53{uQ`s7LHKFLqRYf!yG)7+`YK&W3DPd;4niBlD$36^|yIYuIP^gJ$U) zfDw;rd_ag0g3qn$g09)mx^Z+ z+R<*7O!;u|?)OyyB)hGUq@EZej;pAY3qmae4fxwC3YOBc-HFRGaKj}Mb~V2eb9hLy zcvp9}b|CK7Pg*;;&sM=1!?2Id_tO|pWF73Hjt^ydzH7gYe*{~5-3m^Npg}0=4;lY; z7ih|})#IQR`lXVyWlmgr2K3g(>kKKeonwA3O<#K^_jI4*rX?OF2@_vVl!FA1LxCAJ zO%)=y+ly$OFm~0J;ZJl&HI~}xNUwe^(C2uN^(z(s)V*Xkk1X~lRu8KDs#H|%4V4aU6@l@&qPDpre2xmh1U%i8p%JH zge4mxgPQWx8PS23t4533?hFG9$!jS&;9sVyWRF+d2l~!BN}tB^a;9Xz?I*y6O0_iT z`h&xQl|K^i)r^khp;#iV2f$73;e7&2*LVQRb3|=MIo0KQhadG4NBgu}^IaH(crJzA-7 z>GhO9`xqQeU~c3_dH5Bv*C1)8XiSZ*Olg3dVXP7HE8I z?1C+<*6NG5WsX#zPqTIQSb-8f?Z)?9jB5zxqvktv+Or3Mt2Y;QR5@D?&|;!XEMnEI zMKjtLmzrGqc^^-aV>3#;{CZxqE)e#|&?5F}tKtxOT9xVu|5S+fYi1cuDz3^prOAC7 z#G^0OLNJCBHxrt#l@8cG{Q+`QKrzYgl1h_AaL_qs5&tI;yER=jtvdS)uQC(V+=CD# zeO#&8{0xCVJb1>y@BckV{Vkb|xVaH$ME?v?uL^IgNZ!eXGP4(OE|SB(WPMGQE>-n5 zkMzcudP^mw7_m&jXQal**n}Xn0Y$FhX*B{vvL4@|tnEuB5Hz)(*-1SCZ%9Z1{e%UA zn{R+VaI@PppcCCUkteTK24|W8a}NVtG2M1MpM}odFghjTj+st|@NM#phO^{O zzRH)_$-ZEaQmwiV)S`%OOq;=_ZG{Z}rFK=HMyS%5;igN-G4X@c(VH^(s|;PY_^3jf z$TdY5l9(W}44<`+%7K9)Uh?l@z2Mw=^ib|=g zE?RK(Kxf=<`g3fhV!mx(#o&{0ir1tklTk6thOncR+pU_N%ueY_V^dcsRxh!v8C@cb?=l$ZTN5@6@b@-)VZ>OJKXxY-GU4EeFL0vcCHK97=B7-@m2^x#kLdw*_7g zCrS1D&;#9$y75o}_Hs&d^xhEUp@V#M8Nmyi?`VM=v|8t2f>hrl%>0g_4sTxNspLZa zDO73<(0gFVGhL#_GaD4U?B{>r@=&mwt;kV8bQ+6-@8J?3{rNT8fa?hRO=*s?x{r#A z${8S1??a$SLYbn25$W)IJ>IVut3eLz8DX2!9=Gz!?3}A9E=N}Lf_U&AMx-MOP$&aP zT(nwBJ`mZ})GVV%aTXYThGgcF3Yy1_F@>GNi~e>~;=>*FJrpe}q;|}0+SrbHKDD|B zn-7&WniiZWP&!y_j9P(qw|x}X^igZkw5T!8^I`9J*6w^Nciy_4s|sj)>t0I8LyZey z<##F`FSCf)s}dJBjW132%JG2c!Ox!9X2tRDSRV);zp^^u)clsd}N zc(s4ON#oV4ZKU3_OR7>C!L_;Jn%>G~dZX&;4R4(WqX_DR`8w;c1LZH+W;PrpCHXcJ z$gtw7vF~c$H%j1Bu9}PAjbF#9vtK>=8PN|OA>}~~<=B$#9C}!%Xc7uP-KUeOj_lK7 zyffbiapw+?j#-xYm9cSiFQP37ga?(41UQ!YIb!HB_P%J>?36_|aV+#t!&uXb5@N^f zYz7DmsaK7F@^n~uUwGlHJB;Aiy_aiBn2|q+arMXtnTHZY;L(_woh=41pcVi-&=3|a zRn`1{Z2WBRcuL(h^_nEU)zigGHVhMSp>r|fmkykEyOahCyi(bdOZaP`B`k)I^ zT5G=%ryf#fx+l|Wg+qkYd#062F44mSiC2tvIx0GauiqYZ150F`huV-=b=~oW+4fh- z3}B6LmoL!&(;E2+0gPfqxYKS$i~U<<&Hw3;AO)elIC732V7!mhEV~T3yT|MJLFy~L5NnM?Y{wt5^UwC+n%(n(24#msBeYb1AEMtJ(L!Wu$Fw8jMl1+COq#}}&& zYcexG0k>kN148`I`1rgU*kP|QuCst=GBCjR$E|_`RI-)x`T&yfy+PK9@k0OvR}hlo znyk)widqnXat18pVJ*#V!{*-pmFVu4b)FK`Vxgwd�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 literal 0 HcmV?d00001 diff --git a/documentation/images/transfer-files-status.png b/documentation/images/transfer-files-status.png new file mode 100644 index 0000000000000000000000000000000000000000..943d7b218a166bc8e01a33fecda8533dd067a6e9 GIT binary patch literal 168152 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�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 _{nf!v0Lu;Ew+nk1=JGxUd(H~@ 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 literal 0 HcmV?d00001 From 37d3e4a7a6aaab32d15d350d4aab9667b3f9b0de Mon Sep 17 00:00:00 2001 From: Michael Sverdlov Date: Wed, 14 Jun 2023 14:07:22 +0300 Subject: [PATCH 03/25] Add GolangCI static checks action and fix all found issues (#2011) --- .github/workflows/analysis.yml | 7 +- access_test.go | 10 +- artifactory/cli.go | 194 +++++++------------------ artifactory_test.go | 40 ++--- buildinfo_test.go | 16 +- buildtools/cli.go | 48 ++---- config/cli.go | 28 +--- distribution/cli.go | 20 +-- docker_test.go | 8 +- docs/common/env.go | 2 +- general/cisetup/cisetup.go | 28 ++-- general/project/cli.go | 4 +- go.mod | 5 +- go.sum | 11 +- go_test.go | 23 ++- gradle_test.go | 6 +- inttestutils/docker.go | 10 +- main.go | 15 +- missioncontrol/cli.go | 20 +-- nuget_test.go | 3 +- pipelines/cli.go | 20 +-- plugins/cli.go | 12 +- plugins_test.go | 14 +- scan/cli.go | 33 ++--- transfer_test.go | 14 +- utils/cliutils/utils.go | 3 - utils/progressbar/filesprogressbar.go | 5 +- utils/progressbar/readerprogressbar.go | 1 + utils/progressbar/simpleprogressbar.go | 3 +- utils/summary/summary.go | 4 +- utils/tests/consts.go | 14 +- utils/tests/container.go | 12 +- utils/tests/proxy/server/server.go | 4 +- utils/tests/utils.go | 4 +- xray_test.go | 34 ++--- 35 files changed, 254 insertions(+), 421 deletions(-) diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index 69e89ffe3..d3957b0d4 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -34,6 +34,7 @@ jobs: restore-keys: ${{ runner.os }}-go - name: Run Go vet run: go vet -v ./... + Static-Check: name: Static Check ubuntu-latest runs-on: ubuntu-latest @@ -45,9 +46,11 @@ jobs: with: go-version: 1.20.x - name: Static Code Analysis - uses: dominikh/staticcheck-action@v1 + uses: golangci/golangci-lint-action@v3 with: - install-go: false + args: | + --timeout 5m --out-${NO_FUTURE}format colored-line-number --enable errcheck,gosimple,govet,ineffassign,staticcheck,typecheck,unused,gocritic,asasalint,asciicheck,errchkjson,exportloopref,forcetypeassert,makezero,nilerr,unparam,unconvert,wastedassign,usestdlibvars + Go-Sec: name: Go-Sec ubuntu-latest runs-on: ubuntu-latest diff --git a/access_test.go b/access_test.go index 2dc77a5f8..919eba11c 100644 --- a/access_test.go +++ b/access_test.go @@ -64,7 +64,7 @@ func TestRefreshableAccessTokens(t *testing.T) { // Upload a file and assert the refreshable tokens were generated. artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "") uploadedFiles := 1 - err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.ServerId, "testdata/a/a1.in", uploadedFiles) + err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/a1.in", uploadedFiles) if !assert.NoError(t, err) { return } @@ -80,11 +80,11 @@ func TestRefreshableAccessTokens(t *testing.T) { // Upload a file and assert tokens were refreshed. uploadedFiles++ - err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.ServerId, "testdata/a/a2.in", uploadedFiles) + err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/a2.in", uploadedFiles) if !assert.NoError(t, err) { return } - curAccessToken, curRefreshToken, err = assertTokensChanged(t, tests.ServerId, curAccessToken, curRefreshToken) + curAccessToken, curRefreshToken, err = assertTokensChanged(t, curAccessToken, curRefreshToken) if !assert.NoError(t, err) { return } @@ -92,11 +92,11 @@ func TestRefreshableAccessTokens(t *testing.T) { // Make the token not refresh. Verify Tokens did not refresh. auth.InviteRefreshBeforeExpiryMinutes = 0 uploadedFiles++ - err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.ServerId, "testdata/a/b/b2.in", uploadedFiles) + err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/b/b2.in", uploadedFiles) if !assert.NoError(t, err) { return } - newAccessToken, newRefreshToken, err := getArtifactoryTokensFromConfig(t, tests.ServerId) + newAccessToken, newRefreshToken, err := getArtifactoryTokensFromConfig(t) if !assert.NoError(t, err) { return } diff --git a/artifactory/cli.go b/artifactory/cli.go index 427b3ab1b..6e35b64ad 100644 --- a/artifactory/cli.go +++ b/artifactory/cli.go @@ -128,9 +128,7 @@ func GetCommands() []cli.Command { UsageText: upload.GetArguments(), ArgsUsage: common.CreateEnvVars(upload.EnvVar...), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return uploadCmd(c) - }, + Action: uploadCmd, }, { Name: "download", @@ -141,9 +139,7 @@ func GetCommands() []cli.Command { UsageText: download.GetArguments(), ArgsUsage: common.CreateEnvVars(download.EnvVar...), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return downloadCmd(c) - }, + Action: downloadCmd, }, { Name: "move", @@ -154,9 +150,7 @@ func GetCommands() []cli.Command { UsageText: move.GetArguments(), ArgsUsage: common.CreateEnvVars(move.EnvVar), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return moveCmd(c) - }, + Action: moveCmd, }, { Name: "copy", @@ -167,9 +161,7 @@ func GetCommands() []cli.Command { UsageText: copydocs.GetArguments(), ArgsUsage: common.CreateEnvVars(copydocs.EnvVar), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return copyCmd(c) - }, + Action: copyCmd, }, { Name: "delete", @@ -180,9 +172,7 @@ func GetCommands() []cli.Command { UsageText: delete.GetArguments(), ArgsUsage: common.CreateEnvVars(delete.EnvVar), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return deleteCmd(c) - }, + Action: deleteCmd, }, { Name: "search", @@ -193,9 +183,7 @@ func GetCommands() []cli.Command { UsageText: search.GetArguments(), ArgsUsage: common.CreateEnvVars(search.EnvVar), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return searchCmd(c) - }, + Action: searchCmd, }, { Name: "set-props", @@ -206,9 +194,7 @@ func GetCommands() []cli.Command { UsageText: setprops.GetArguments(), ArgsUsage: common.CreateEnvVars(setprops.EnvVar), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return setPropsCmd(c) - }, + Action: setPropsCmd, }, { Name: "delete-props", @@ -219,9 +205,7 @@ func GetCommands() []cli.Command { UsageText: deleteprops.GetArguments(), ArgsUsage: common.CreateEnvVars(deleteprops.EnvVar), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return deletePropsCmd(c) - }, + Action: deletePropsCmd, }, { Name: "build-publish", @@ -232,9 +216,7 @@ func GetCommands() []cli.Command { UsageText: buildpublish.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return buildPublishCmd(c) - }, + Action: buildPublishCmd, }, { Name: "build-collect-env", @@ -245,9 +227,7 @@ func GetCommands() []cli.Command { UsageText: buildcollectenv.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return buildCollectEnvCmd(c) - }, + Action: buildCollectEnvCmd, }, { Name: "build-append", @@ -258,9 +238,7 @@ func GetCommands() []cli.Command { UsageText: buildappend.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return buildAppendCmd(c) - }, + Action: buildAppendCmd, }, { Name: "build-add-dependencies", @@ -271,9 +249,7 @@ func GetCommands() []cli.Command { UsageText: buildadddependencies.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return buildAddDependenciesCmd(c) - }, + Action: buildAddDependenciesCmd, }, { Name: "build-add-git", @@ -284,9 +260,7 @@ func GetCommands() []cli.Command { UsageText: buildaddgit.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return buildAddGitCmd(c) - }, + Action: buildAddGitCmd, }, { Name: "build-scan", @@ -309,9 +283,7 @@ func GetCommands() []cli.Command { UsageText: buildclean.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return buildCleanCmd(c) - }, + Action: buildCleanCmd, }, { Name: "build-promote", @@ -322,9 +294,7 @@ func GetCommands() []cli.Command { UsageText: buildpromote.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return buildPromoteCmd(c) - }, + Action: buildPromoteCmd, }, { Name: "build-discard", @@ -335,9 +305,7 @@ func GetCommands() []cli.Command { UsageText: builddiscard.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return buildDiscardCmd(c) - }, + Action: buildDiscardCmd, }, { Name: "git-lfs-clean", @@ -348,9 +316,7 @@ func GetCommands() []cli.Command { UsageText: gitlfsclean.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return gitLfsCleanCmd(c) - }, + Action: gitLfsCleanCmd, }, { Name: "mvn-config", @@ -411,9 +377,7 @@ func GetCommands() []cli.Command { UsageText: dockerpromote.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return dockerPromoteCmd(c) - }, + Action: dockerPromoteCmd, }, { Name: "docker-push", @@ -476,9 +440,7 @@ func GetCommands() []cli.Command { UsageText: builddockercreate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return BuildDockerCreateCmd(c) - }, + Action: BuildDockerCreateCmd, }, { Name: "oc", // Only 'oc start-build' is supported @@ -489,9 +451,7 @@ func GetCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return ocStartBuildCmd(c) - }, + Action: ocStartBuildCmd, }, { Name: "npm-config", @@ -602,9 +562,7 @@ func GetCommands() []cli.Command { HelpName: corecommon.CreateUsage("rt nuget-deps-tree", nugettree.GetDescription(), nugettree.Usage), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return nugetDepsTreeCmd(c) - }, + Action: nugetDepsTreeCmd, }, { Name: "dotnet-config", @@ -677,9 +635,7 @@ func GetCommands() []cli.Command { HelpName: corecommon.CreateUsage("rt ping", ping.GetDescription(), ping.Usage), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return pingCmd(c) - }, + Action: pingCmd, }, { Name: "curl", @@ -691,9 +647,7 @@ func GetCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), SkipFlagParsing: true, - Action: func(c *cli.Context) error { - return curlCmd(c) - }, + Action: curlCmd, }, { Name: "pip-config", @@ -729,9 +683,7 @@ func GetCommands() []cli.Command { UsageText: repotemplate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return repoTemplateCmd(c) - }, + Action: repoTemplateCmd, }, { Name: "repo-create", @@ -742,9 +694,7 @@ func GetCommands() []cli.Command { UsageText: repocreate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return repoCreateCmd(c) - }, + Action: repoCreateCmd, }, { Name: "repo-update", @@ -755,9 +705,7 @@ func GetCommands() []cli.Command { UsageText: repoupdate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return repoUpdateCmd(c) - }, + Action: repoUpdateCmd, }, { Name: "repo-delete", @@ -768,9 +716,7 @@ func GetCommands() []cli.Command { UsageText: repodelete.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return repoDeleteCmd(c) - }, + Action: repoDeleteCmd, }, { Name: "replication-template", @@ -781,9 +727,7 @@ func GetCommands() []cli.Command { UsageText: replicationtemplate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return replicationTemplateCmd(c) - }, + Action: replicationTemplateCmd, }, { Name: "replication-create", @@ -794,9 +738,7 @@ func GetCommands() []cli.Command { UsageText: replicationcreate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return replicationCreateCmd(c) - }, + Action: replicationCreateCmd, }, { Name: "replication-delete", @@ -807,9 +749,7 @@ func GetCommands() []cli.Command { UsageText: replicationdelete.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return replicationDeleteCmd(c) - }, + Action: replicationDeleteCmd, }, { Name: "permission-target-template", @@ -819,9 +759,7 @@ func GetCommands() []cli.Command { UsageText: permissiontargettemplate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return permissionTargetTemplateCmd(c) - }, + Action: permissionTargetTemplateCmd, }, { Name: "permission-target-create", @@ -832,9 +770,7 @@ func GetCommands() []cli.Command { UsageText: permissiontargetcreate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return permissionTargetCreateCmd(c) - }, + Action: permissionTargetCreateCmd, }, { Name: "permission-target-update", @@ -845,9 +781,7 @@ func GetCommands() []cli.Command { UsageText: permissiontargetupdate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return permissionTargetUpdateCmd(c) - }, + Action: permissionTargetUpdateCmd, }, { Name: "permission-target-delete", @@ -858,9 +792,7 @@ func GetCommands() []cli.Command { UsageText: permissiontargetdelete.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return permissionTargetDeleteCmd(c) - }, + Action: permissionTargetDeleteCmd, }, { Name: "user-create", @@ -869,9 +801,7 @@ func GetCommands() []cli.Command { HelpName: corecommon.CreateUsage("rt user-create", usercreate.GetDescription(), usercreate.Usage), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return userCreateCmd(c) - }, + Action: userCreateCmd, }, { Name: "users-create", @@ -881,9 +811,7 @@ func GetCommands() []cli.Command { HelpName: corecommon.CreateUsage("rt uc", userscreate.GetDescription(), userscreate.Usage), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return usersCreateCmd(c) - }, + Action: usersCreateCmd, }, { Name: "users-delete", @@ -894,9 +822,7 @@ func GetCommands() []cli.Command { UsageText: usersdelete.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return usersDeleteCmd(c) - }, + Action: usersDeleteCmd, }, { Name: "group-create", @@ -907,9 +833,7 @@ func GetCommands() []cli.Command { UsageText: groupcreate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return groupCreateCmd(c) - }, + Action: groupCreateCmd, }, { Name: "group-add-users", @@ -920,9 +844,7 @@ func GetCommands() []cli.Command { UsageText: groupaddusers.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return groupAddUsersCmd(c) - }, + Action: groupAddUsersCmd, }, { Name: "group-delete", @@ -933,9 +855,7 @@ func GetCommands() []cli.Command { UsageText: groupdelete.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return groupDeleteCmd(c) - }, + Action: groupDeleteCmd, }, { Name: "access-token-create", @@ -946,9 +866,7 @@ func GetCommands() []cli.Command { UsageText: accesstokencreate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return accessTokenCreateCmd(c) - }, + Action: accessTokenCreateCmd, }, { Name: "transfer-settings", @@ -956,9 +874,7 @@ func GetCommands() []cli.Command { HelpName: corecommon.CreateUsage("rt transfer-settings", transfersettings.GetDescription(), transfersettings.Usage), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return transferSettingsCmd() - }, + Action: transferSettingsCmd, }, { Name: "transfer-config", @@ -968,9 +884,7 @@ func GetCommands() []cli.Command { UsageText: transferconfig.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return transferConfigCmd(c) - }, + Action: transferConfigCmd, }, { Name: "transfer-config-merge", @@ -980,9 +894,7 @@ func GetCommands() []cli.Command { UsageText: transferconfigmerge.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return transferConfigMergeCmd(c) - }, + Action: transferConfigMergeCmd, }, { Name: "transfer-files", @@ -992,9 +904,7 @@ func GetCommands() []cli.Command { UsageText: transferfiles.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return transferFilesCmd(c) - }, + Action: transferFilesCmd, }, { Name: "transfer-plugin-install", @@ -1004,9 +914,7 @@ func GetCommands() []cli.Command { UsageText: transferplugininstall.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return dataTransferPluginInstallCmd(c) - }, + Action: dataTransferPluginInstallCmd, }, }) } @@ -1062,12 +970,14 @@ func getRetryWaitTime(c *cli.Context) (waitMilliSecs int, err error) { waitTimeStringValue := c.String("retry-wait-time") useSeconds := false if waitTimeStringValue != "" { - if strings.HasSuffix(waitTimeStringValue, "ms") { + switch { + case strings.HasSuffix(waitTimeStringValue, "ms"): waitTimeStringValue = strings.TrimSuffix(waitTimeStringValue, "ms") - } else if strings.HasSuffix(waitTimeStringValue, "s") { + + case strings.HasSuffix(waitTimeStringValue, "s"): useSeconds = true waitTimeStringValue = strings.TrimSuffix(waitTimeStringValue, "s") - } else { + default: err = getRetryWaitTimeVerificationError() return } @@ -1078,7 +988,7 @@ func getRetryWaitTime(c *cli.Context) (waitMilliSecs int, err error) { } // Convert seconds to milliseconds if useSeconds { - waitMilliSecs = waitMilliSecs * 1000 + waitMilliSecs *= 1000 } } return diff --git a/artifactory_test.go b/artifactory_test.go index b8a9ae04a..250545b05 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -123,7 +123,7 @@ func authenticate(configCli bool) string { // Removed the ssh-passphrase flag that cannot be passed to with a config command func createConfigJfrogCLI(cred string) *tests.JfrogCli { if strings.Contains(cred, " --ssh-passphrase=") { - cred = strings.Replace(cred, " --ssh-passphrase="+*tests.JfrogSshPassphrase, "", -1) + cred = strings.ReplaceAll(cred, " --ssh-passphrase="+*tests.JfrogSshPassphrase, "") } return tests.NewJfrogCli(execMain, "jfrog config", cred) } @@ -1248,10 +1248,10 @@ func TestArtifactoryDownloadAndExplodeSpecialChars(t *testing.T) { cleanArtifactoryTest() } -func verifyExistAndCleanDir(t *testing.T, GetExtractedDownload func() []string) { +func verifyExistAndCleanDir(t *testing.T, getExtractedDownload func() []string) { paths, err := fileutils.ListFilesRecursiveWalkIntoDirSymlink(tests.Out, false) assert.NoError(t, err) - tests.VerifyExistLocally(GetExtractedDownload(), paths, t) + tests.VerifyExistLocally(getExtractedDownload(), paths, t) clientTestUtils.RemoveAllAndAssert(t, tests.Out) assert.NoError(t, fileutils.CreateDirIfNotExist(tests.Out)) } @@ -4216,7 +4216,7 @@ func TestArtifactoryBuildDiscard(t *testing.T) { jsonResponse = getAllBuildsByBuildName(client, tests.RtBuildName1, t, http.StatusNotFound) assert.Zero(t, jsonResponse, "Incorrect operation of build-discard by max-days.") - //Cleanup + // Cleanup inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.RtBuildName1, artHttpDetails) cleanArtifactoryTest() } @@ -5255,11 +5255,11 @@ func TestRefreshableArtifactoryTokens(t *testing.T) { // Upload a file and assert the refreshable tokens were generated. artifactoryCommandExecutor := tests.NewJfrogCli(execMain, "jfrog rt", "") uploadedFiles := 1 - err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.ServerId, "testdata/a/a1.in", uploadedFiles) + err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/a1.in", uploadedFiles) if err != nil { return } - curAccessToken, curRefreshToken, err := getArtifactoryTokensFromConfig(t, tests.ServerId) + curAccessToken, curRefreshToken, err := getArtifactoryTokensFromConfig(t) if err != nil { return } @@ -5271,11 +5271,11 @@ func TestRefreshableArtifactoryTokens(t *testing.T) { // Upload a file and assert tokens were refreshed. uploadedFiles++ - err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.ServerId, "testdata/a/a2.in", uploadedFiles) + err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/a2.in", uploadedFiles) if err != nil { return } - curAccessToken, curRefreshToken, err = assertTokensChanged(t, tests.ServerId, curAccessToken, curRefreshToken) + curAccessToken, curRefreshToken, err = assertTokensChanged(t, curAccessToken, curRefreshToken) if err != nil { return } @@ -5286,11 +5286,11 @@ func TestRefreshableArtifactoryTokens(t *testing.T) { return } uploadedFiles++ - err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.ServerId, "testdata/a/a3.in", uploadedFiles) + err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/a3.in", uploadedFiles) if err != nil { return } - curAccessToken, curRefreshToken, err = assertTokensChanged(t, tests.ServerId, curAccessToken, curRefreshToken) + curAccessToken, curRefreshToken, err = assertTokensChanged(t, curAccessToken, curRefreshToken) if err != nil { return } @@ -5301,11 +5301,11 @@ func TestRefreshableArtifactoryTokens(t *testing.T) { return } uploadedFiles++ - err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.ServerId, "testdata/a/b/b1.in", uploadedFiles) + err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/b/b1.in", uploadedFiles) if err != nil { return } - curAccessToken, curRefreshToken, err = assertTokensChanged(t, tests.ServerId, curAccessToken, curRefreshToken) + curAccessToken, curRefreshToken, err = assertTokensChanged(t, curAccessToken, curRefreshToken) if err != nil { return } @@ -5313,11 +5313,11 @@ func TestRefreshableArtifactoryTokens(t *testing.T) { // Make the token not refresh. Verify Tokens did not refresh. auth.RefreshBeforeExpiryMinutes = 0 uploadedFiles++ - err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, tests.ServerId, "testdata/a/b/b2.in", uploadedFiles) + err = uploadWithSpecificServerAndVerify(t, artifactoryCommandExecutor, "testdata/a/b/b2.in", uploadedFiles) if err != nil { return } - newAccessToken, newRefreshToken, err := getArtifactoryTokensFromConfig(t, tests.ServerId) + newAccessToken, newRefreshToken, err := getArtifactoryTokensFromConfig(t) if err != nil { return } @@ -5358,8 +5358,8 @@ func setPasswordInConfig(t *testing.T, serverId, password string) error { return nil } -func getArtifactoryTokensFromConfig(t *testing.T, serverId string) (accessToken, refreshToken string, err error) { - details, err := config.GetSpecificConfig(serverId, false, false) +func getArtifactoryTokensFromConfig(t *testing.T) (accessToken, refreshToken string, err error) { + details, err := config.GetSpecificConfig(tests.ServerId, false, false) if err != nil { assert.NoError(t, err) return "", "", err @@ -5367,8 +5367,8 @@ func getArtifactoryTokensFromConfig(t *testing.T, serverId string) (accessToken, return details.AccessToken, details.ArtifactoryRefreshToken, nil } -func assertTokensChanged(t *testing.T, serverId, curAccessToken, curRefreshToken string) (newAccessToken, newRefreshToken string, err error) { - newAccessToken, newRefreshToken, err = getArtifactoryTokensFromConfig(t, serverId) +func assertTokensChanged(t *testing.T, curAccessToken, curRefreshToken string) (newAccessToken, newRefreshToken string, err error) { + newAccessToken, newRefreshToken, err = getArtifactoryTokensFromConfig(t) if err != nil { assert.NoError(t, err) return "", "", err @@ -5378,8 +5378,8 @@ func assertTokensChanged(t *testing.T, serverId, curAccessToken, curRefreshToken return newAccessToken, newRefreshToken, nil } -func uploadWithSpecificServerAndVerify(t *testing.T, cli *tests.JfrogCli, serverId string, source string, expectedResults int) error { - err := cli.Exec("upload", source, tests.RtRepo1, "--server-id="+serverId) +func uploadWithSpecificServerAndVerify(t *testing.T, cli *tests.JfrogCli, source string, expectedResults int) error { + err := cli.Exec("upload", source, tests.RtRepo1, "--server-id="+tests.ServerId) if err != nil { assert.NoError(t, err) return err diff --git a/buildinfo_test.go b/buildinfo_test.go index 9231d3d7f..a04443559 100644 --- a/buildinfo_test.go +++ b/buildinfo_test.go @@ -199,7 +199,7 @@ func TestBuildPublishDetailedSummary(t *testing.T) { assert.NoError(t, err) runRt(t, "upload", "--spec="+specFile, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber) // Verify build dir is not empty - assert.NotEmpty(t, getFilesFromBuildDir(t, tests.RtBuildName1, buildNumber, "")) + assert.NotEmpty(t, getFilesFromBuildDir(t, tests.RtBuildName1, buildNumber)) buffer, _, previousLog := coretests.RedirectLogOutputToBuffer() // Restore previous logger when the function returns @@ -224,7 +224,7 @@ func TestBuildPublishDryRun(t *testing.T) { assert.NoError(t, err) runRt(t, "upload", "--spec="+specFile, "--build-name="+tests.RtBuildName1, "--build-number="+buildNumber) // Verify build dir is not empty - assert.NotEmpty(t, getFilesFromBuildDir(t, tests.RtBuildName1, buildNumber, "")) + assert.NotEmpty(t, getFilesFromBuildDir(t, tests.RtBuildName1, buildNumber)) buffer, _, previousLog := coretests.RedirectLogOutputToBuffer() // Restore previous logger when the function returns @@ -235,7 +235,7 @@ func TestBuildPublishDryRun(t *testing.T) { verifyBuildPublishOutput(t, buffer, true) // Verify build dir is not empty. - assert.NotEmpty(t, getFilesFromBuildDir(t, tests.RtBuildName1, buildNumber, "")) + assert.NotEmpty(t, getFilesFromBuildDir(t, tests.RtBuildName1, buildNumber)) // Verify build was not published. _, found, err := tests.GetBuildInfo(serverDetails, tests.RtBuildName1, buildNumber) if err != nil { @@ -252,7 +252,7 @@ func TestBuildPublishDryRun(t *testing.T) { verifyBuildPublishOutput(t, buffer, false) // Verify build dir is empty - assert.Empty(t, getFilesFromBuildDir(t, tests.RtBuildName1, buildNumber, "")) + assert.Empty(t, getFilesFromBuildDir(t, tests.RtBuildName1, buildNumber)) // Verify build was published publishedBuildInfo, found, err := tests.GetBuildInfo(serverDetails, tests.RtBuildName1, buildNumber) if err != nil { @@ -282,7 +282,10 @@ func verifyBuildPublishOutput(t *testing.T, buffer *bytes.Buffer, dryRun bool) { } } -func getFilesFromBuildDir(t *testing.T, buildName, buildNumber, projectKey string) []os.DirEntry { +// The linter has an issue with buildNumber that is always the same number, but we do it on purpose. +// +//nolint:unparam +func getFilesFromBuildDir(t *testing.T, buildName, buildNumber string) []os.DirEntry { buildDir, err := utils.GetBuildDir(buildName, buildNumber, "") assert.NoError(t, err) @@ -867,7 +870,8 @@ func validateBuildAddDepsBuildInfo(t *testing.T, buildInfoTestParams buildAddDep } buildInfo := publishedBuildInfo.BuildInfo if buildInfo.Modules == nil || len(buildInfo.Modules) == 0 { - buildInfoString, _ := json.Marshal(buildInfo) + buildInfoString, err := json.Marshal(buildInfo) + assert.NoError(t, err) // Case no module was not created assert.Failf(t, "%s test with the command: \nrt bad %s \nexpected to have module with the following dependencies: \n%s \nbut has no modules: \n%s", buildInfoTestParams.description, buildInfoTestParams.commandArgs, buildInfoTestParams.expectedDependencies, buildInfoString) diff --git a/buildtools/cli.go b/buildtools/cli.go index 8ef8f3c8d..4d1f9762d 100644 --- a/buildtools/cli.go +++ b/buildtools/cli.go @@ -84,9 +84,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return MvnCmd(c) - }, + Action: MvnCmd, }, { Name: "gradle-config", @@ -111,9 +109,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return GradleCmd(c) - }, + Action: GradleCmd, }, { Name: "yarn-config", @@ -137,9 +133,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return YarnCmd(c) - }, + Action: YarnCmd, }, { Name: "nuget-config", @@ -164,9 +158,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return NugetCmd(c) - }, + Action: NugetCmd, }, { Name: "dotnet-config", @@ -191,9 +183,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return DotnetCmd(c) - }, + Action: DotnetCmd, }, { Name: "go-config", @@ -219,9 +209,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return GoCmd(c) - }, + Action: GoCmd, }, { Name: "go-publish", @@ -233,9 +221,7 @@ func GetCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return GoPublishCmd(c) - }, + Action: GoPublishCmd, }, { Name: "pip-config", @@ -260,9 +246,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return PipCmd(c) - }, + Action: PipCmd, }, { Name: "pipenv-config", @@ -287,9 +271,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return PipenvCmd(c) - }, + Action: PipenvCmd, }, { Name: "poetry-config", @@ -314,9 +296,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return PoetryCmd(c) - }, + Action: PoetryCmd, }, { Name: "npm-config", @@ -361,9 +341,7 @@ func GetCommands() []cli.Command { }(), BashComplete: corecommon.CreateBashCompletionFunc("push", "pull", "scan"), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return dockerCmd(c) - }, + Action: dockerCmd, }, { Name: "terraform-config", @@ -389,9 +367,7 @@ func GetCommands() []cli.Command { SkipFlagParsing: true, BashComplete: corecommon.CreateBashCompletionFunc(), Category: buildToolsCategory, - Action: func(c *cli.Context) error { - return terraformCmd(c) - }, + Action: terraformCmd, }, }) } diff --git a/config/cli.go b/config/cli.go index 8f7ab75aa..b55d5dadc 100644 --- a/config/cli.go +++ b/config/cli.go @@ -31,9 +31,7 @@ func GetCommands() []cli.Command { Flags: cliutils.GetCommandFlags(cliutils.AddConfig), HelpName: corecommon.CreateUsage("c add", add.GetDescription(), add.Usage), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return addCmd(c) - }, + Action: addCmd, }, { Name: "edit", @@ -41,9 +39,7 @@ func GetCommands() []cli.Command { Flags: cliutils.GetCommandFlags(cliutils.EditConfig), HelpName: corecommon.CreateUsage("c edit", edit.GetDescription(), edit.Usage), BashComplete: corecommon.CreateBashCompletionFunc(commands.GetAllServerIds()...), - Action: func(c *cli.Context) error { - return editCmd(c) - }, + Action: editCmd, }, { Name: "show", @@ -51,9 +47,7 @@ func GetCommands() []cli.Command { Usage: show.GetDescription(), HelpName: corecommon.CreateUsage("c show", show.GetDescription(), show.Usage), BashComplete: corecommon.CreateBashCompletionFunc(commands.GetAllServerIds()...), - Action: func(c *cli.Context) error { - return showCmd(c) - }, + Action: showCmd, }, { Name: "remove", @@ -62,9 +56,7 @@ func GetCommands() []cli.Command { Flags: cliutils.GetCommandFlags(cliutils.DeleteConfig), HelpName: corecommon.CreateUsage("c rm", remove.GetDescription(), remove.Usage), BashComplete: corecommon.CreateBashCompletionFunc(commands.GetAllServerIds()...), - Action: func(c *cli.Context) error { - return deleteCmd(c) - }, + Action: deleteCmd, }, { Name: "import", @@ -72,9 +64,7 @@ func GetCommands() []cli.Command { Usage: importcmd.GetDescription(), HelpName: corecommon.CreateUsage("c import", importcmd.GetDescription(), importcmd.Usage), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return importCmd(c) - }, + Action: importCmd, }, { Name: "export", @@ -82,18 +72,14 @@ func GetCommands() []cli.Command { Usage: exportcmd.GetDescription(), HelpName: corecommon.CreateUsage("c export", exportcmd.GetDescription(), exportcmd.Usage), BashComplete: corecommon.CreateBashCompletionFunc(commands.GetAllServerIds()...), - Action: func(c *cli.Context) error { - return exportCmd(c) - }, + Action: exportCmd, }, { Name: "use", Usage: use.GetDescription(), HelpName: corecommon.CreateUsage("c use", use.GetDescription(), use.Usage), BashComplete: corecommon.CreateBashCompletionFunc(commands.GetAllServerIds()...), - Action: func(c *cli.Context) error { - return useCmd(c) - }, + Action: useCmd, }, }) } diff --git a/distribution/cli.go b/distribution/cli.go index 875af521c..81d04c537 100644 --- a/distribution/cli.go +++ b/distribution/cli.go @@ -35,9 +35,7 @@ func GetCommands() []cli.Command { UsageText: releasebundlecreate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: coreCommonDocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return releaseBundleCreateCmd(c) - }, + Action: releaseBundleCreateCmd, }, { Name: "release-bundle-update", @@ -48,9 +46,7 @@ func GetCommands() []cli.Command { UsageText: releasebundleupdate.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: coreCommonDocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return releaseBundleUpdateCmd(c) - }, + Action: releaseBundleUpdateCmd, }, { Name: "release-bundle-sign", @@ -61,9 +57,7 @@ func GetCommands() []cli.Command { UsageText: releasebundlesign.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: coreCommonDocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return releaseBundleSignCmd(c) - }, + Action: releaseBundleSignCmd, }, { Name: "release-bundle-distribute", @@ -74,9 +68,7 @@ func GetCommands() []cli.Command { UsageText: releasebundledistribute.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: coreCommonDocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return releaseBundleDistributeCmd(c) - }, + Action: releaseBundleDistributeCmd, }, { Name: "release-bundle-delete", @@ -87,9 +79,7 @@ func GetCommands() []cli.Command { UsageText: releasebundledelete.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: coreCommonDocs.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return releaseBundleDeleteCmd(c) - }, + Action: releaseBundleDeleteCmd, }, }) } diff --git a/docker_test.go b/docker_test.go index f418dc2d5..f0c76ef12 100644 --- a/docker_test.go +++ b/docker_test.go @@ -209,10 +209,8 @@ func TestPushFatManifestImage(t *testing.T) { // Docker daemon take times to load. In order to check if it's available we wait for a log message to indications that the Docker daemon has finished initializing. WaitFor(wait.ForLog("API listen on /var/run/docker.sock").WithStartupTimeout(5*time.Minute)). Remove(). - Build(ctx, t, true) - if err != nil { - t.Errorf("Couldn't run create buildx image. Error: %s", err.Error()) - } + Build(ctx, true) + assert.NoError(t, err, "Couldn't run create buildx image.") defer func() { assert.NoError(t, testContainer.Terminate(ctx)) }() // Enable the builder util in the container. @@ -495,7 +493,7 @@ func runKaniko(t *testing.T, imageToPush string) string { Mount(credentialsFile, "/kaniko/.docker/config.json", true). Cmd("--dockerfile="+dockerFile, "--destination="+imageToPush, "--insecure", "--skip-tls-verify", "--image-name-with-digest-file="+KanikoOutputFile). WaitFor(wait.ForExit().WithExitTimeout(300000*time.Millisecond)). - Build(context.Background(), t, true) + Build(context.Background(), true) assert.NoError(t, err) // Return a file contains the image metadata which was built by Kaniko. diff --git a/docs/common/env.go b/docs/common/env.go index 7e016e24c..105b74148 100644 --- a/docs/common/env.go +++ b/docs/common/env.go @@ -129,5 +129,5 @@ func GetGlobalEnvVars() string { func CreateEnvVars(envVars ...string) string { var s []string s = append(s, envVars...) - return strings.Join(s[:], "\n\n") + return strings.Join(s, "\n\n") } diff --git a/general/cisetup/cisetup.go b/general/cisetup/cisetup.go index 1396c8559..450c04ad5 100644 --- a/general/cisetup/cisetup.go +++ b/general/cisetup/cisetup.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/json" "fmt" + "golang.org/x/exp/slices" "os" "path" "path/filepath" @@ -170,8 +171,8 @@ func (cc *CiSetupCommand) Run() error { return err } // Ask the user which CI he tries to setup - err = cc.ciProviderPhase() - err = saveIfNoError(err, cc.data) + cc.ciProviderPhase() + err = saveVcsConf(cc.data) if err != nil { return err } @@ -298,6 +299,7 @@ func getPipelinesToken() (string, error) { if err != nil { return "", err } + //nolint:unconvert byteToken, err = term.ReadPassword(int(syscall.Stdin)) if err != nil { return "", errorutils.CheckError(err) @@ -494,7 +496,7 @@ func (cc *CiSetupCommand) getGithubActionsCompletionInstruction(githubActionFile } func (cc *CiSetupCommand) logCompletionInstruction(ciSpecificInstructions []string) error { - instructions := append(ciSpecificInstructions, + instructions := append(slices.Clone(ciSpecificInstructions), coreutils.PrintTitle("Allowing developers to access this pipeline from their IDE"), "You have the option of viewing the new pipeline's runs from within IntelliJ IDEA.", "To achieve this, follow these steps:", @@ -519,7 +521,7 @@ func getPipelineUiPath(pipelinesUrl, pipelineName string) string { func (cc *CiSetupCommand) publishFirstBuild() (err error) { cc.data.BuildName = fmt.Sprintf("%s-%s", cc.data.RepositoryName, cc.data.GitBranch) // Run BAG Command (in order to publish the first, empty, build info) - buildAddGitConfigurationCmd := buildinfo.NewBuildAddGitCommand().SetDotGitPath(cc.data.LocalDirPath).SetServerId(cisetup.ConfigServerId) //.SetConfigFilePath(c.String("config")) + buildAddGitConfigurationCmd := buildinfo.NewBuildAddGitCommand().SetDotGitPath(cc.data.LocalDirPath).SetServerId(cisetup.ConfigServerId) buildConfiguration := rtutils.NewBuildConfiguration(cc.data.BuildName, DefaultFirstBuildNumber, "", "") buildAddGitConfigurationCmd = buildAddGitConfigurationCmd.SetBuildConfiguration(buildConfiguration) log.Info("Generating an initial build-info...") @@ -567,10 +569,10 @@ func (cc *CiSetupCommand) xrayConfigPhase() (err error) { err = xrayManager.CreatePolicy(policyParams) if err != nil { // In case the error is from type PolicyAlreadyExistsError, we should continue with the regular flow. - if _, ok := err.(*xrayservices.PolicyAlreadyExistsError); !ok { + if paeErr, ok := err.(*xrayservices.PolicyAlreadyExistsError); !ok { return err } else { - log.Debug(err.(*xrayservices.PolicyAlreadyExistsError).InnerError) + log.Debug(paeErr.InnerError) } } // Create new default watcher. @@ -589,10 +591,10 @@ func (cc *CiSetupCommand) xrayConfigPhase() (err error) { err = xrayManager.CreateWatch(watchParams) if err != nil { // In case the error is from type WatchAlreadyExistsError, we should continue with the regular flow. - if _, ok := err.(*xrayservices.WatchAlreadyExistsError); !ok { + if waeErr, ok := err.(*xrayservices.WatchAlreadyExistsError); !ok { return err } else { - log.Debug(err.(*xrayservices.WatchAlreadyExistsError).InnerError) + log.Debug(waeErr.InnerError) err = nil } } @@ -963,6 +965,7 @@ func (cc *CiSetupCommand) gitPhase() (err error) { if err != nil { return err } + //nolint:unconvert byteToken, err := term.ReadPassword(int(syscall.Stdin)) if err != nil { log.Error(err) @@ -986,10 +989,9 @@ func (cc *CiSetupCommand) gitPhase() (err error) { } } -func (cc *CiSetupCommand) ciProviderPhase() (err error) { - var ciType string +func (cc *CiSetupCommand) ciProviderPhase() { for { - ciType, err = promptCiProviderSelection() + ciType, err := promptCiProviderSelection() if err != nil { log.Error(err) continue @@ -1027,7 +1029,7 @@ func (cc *CiSetupCommand) ciProviderPhase() (err error) { _, err = pipelinesMgr.GetSystemInfo() if err == nil { cc.data.CiType = cisetup.CiType(ciType) - return nil + return } log.Error(err) if _, ok := err.(*pipelinesservices.PipelinesNotAvailableError); ok { @@ -1038,7 +1040,7 @@ func (cc *CiSetupCommand) ciProviderPhase() (err error) { } } else { // The user doesn't choose Pipelines. cc.data.CiType = cisetup.CiType(ciType) - return nil + return } } } diff --git a/general/project/cli.go b/general/project/cli.go index 64c32726c..f1a3dd758 100644 --- a/general/project/cli.go +++ b/general/project/cli.go @@ -23,9 +23,7 @@ func GetCommands() []cli.Command { Flags: cliutils.GetCommandFlags(cliutils.InitProject), HelpName: corecommon.CreateUsage("project init", projectinit.GetDescription(), projectinit.Usage), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return initProject(c) - }, + Action: initProject, }, }) } diff --git a/go.mod b/go.mod index c91291965..ce09de2c6 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/agnivade/levenshtein v1.1.1 github.com/buger/jsonparser v1.1.1 github.com/go-git/go-git/v5 v5.7.0 - github.com/gocarina/gocsv v0.0.0-20230513223533-9ddd7fd60602 + github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 github.com/jfrog/build-info-go v1.9.6 github.com/jfrog/gofrog v1.3.0 github.com/jfrog/jfrog-cli-core/v2 v2.35.0 @@ -16,12 +16,13 @@ require ( github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.20.1 - github.com/urfave/cli v1.22.13 + github.com/urfave/cli v1.22.12 github.com/vbauerster/mpb/v7 v7.5.3 github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 golang.org/x/term v0.8.0 gopkg.in/yaml.v2 v2.4.0 + ) require ( diff --git a/go.sum b/go.sum index 35e394b39..60006e5ce 100644 --- a/go.sum +++ b/go.sum @@ -109,6 +109,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v23.0.5+incompatible h1:DaxtlTJjFSnLOXVNUBU1+6kXGz2lpDoEAH6QoxaSg8k= @@ -147,8 +149,8 @@ github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhc github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/gocarina/gocsv v0.0.0-20230513223533-9ddd7fd60602 h1:HSpPf+lPYwzoJNup34uegmOQk5Qm83S+wpu8anTDJkg= -github.com/gocarina/gocsv v0.0.0-20230513223533-9ddd7fd60602/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= +github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 h1:LCGzZb4kMUUjMUzLxxqSJBwo9szUO0tK8cOxnEOT4Jc= +github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -376,7 +378,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= @@ -388,8 +389,8 @@ github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oW github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.13 h1:wsLILXG8qCJNse/qAgLNf23737Cx05GflHg/PJGe1Ok= -github.com/urfave/cli v1.22.13/go.mod h1:VufqObjsMTF2BBwKawpx9R8eAneNEWhoO0yx8Vd+FkE= +github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8= +github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/vbauerster/mpb/v7 v7.5.3 h1:BkGfmb6nMrrBQDFECR/Q7RkKCw7ylMetCb4079CGs4w= github.com/vbauerster/mpb/v7 v7.5.3/go.mod h1:i+h4QY6lmLvBNK2ah1fSreiw3ajskRlBp9AhY/PnuOE= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= diff --git a/go_test.go b/go_test.go index d2559db76..d51d422ff 100644 --- a/go_test.go +++ b/go_test.go @@ -31,7 +31,7 @@ func TestGoConfigWithModuleNameChange(t *testing.T) { wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") - prepareGoProject("project1", "", t, true) + prepareGoProject("project1", t, true) runGo(t, ModuleNameJFrogTest, tests.GoBuildName, buildNumber, 4, 0, "go", "build", "--mod=mod", "--build-name="+tests.GoBuildName, "--build-number="+buildNumber, "--module="+ModuleNameJFrogTest) clientTestUtils.ChangeDirAndAssert(t, wd) @@ -44,7 +44,7 @@ func TestGoGetSpecificVersion(t *testing.T) { buildNumber := "1" wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") - prepareGoProject("project1", "", t, true) + prepareGoProject("project1", t, true) // Build and publish a go project. // We do so in order to make sure the rsc.io/quote:v1.5.2 will be available for the get command runGo(t, "", tests.GoBuildName, buildNumber, 4, 0, "go", "build", "--mod=mod", "--build-name="+tests.GoBuildName, "--build-number="+buildNumber) @@ -87,7 +87,7 @@ func TestGoGetNestedPackage(t *testing.T) { defer cleanUpFunc() wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") - prepareGoProject("project1", "", t, true) + prepareGoProject("project1", t, true) jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") // Download 'mockgen', which is a nested package inside 'github.com/golang/mock@v1.4.1'. Then validate it was downloaded correctly. @@ -112,9 +112,9 @@ func TestGoPublishResolve(t *testing.T) { defer cleanUpFunc() wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") - project1Path := prepareGoProject("project1", "", t, true) + project1Path := prepareGoProject("project1", t, true) clientTestUtils.ChangeDirAndAssert(t, wd) - project2Path := prepareGoProject("project2", "", t, true) + project2Path := prepareGoProject("project2", t, true) clientTestUtils.ChangeDirAndAssert(t, project1Path) // Build the first project and download its dependencies from Artifactory @@ -145,7 +145,7 @@ func TestGoPublishWithDetailedSummary(t *testing.T) { // Init environment wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") - projectPath := prepareGoProject("project1", "", t, true) + projectPath := prepareGoProject("project1", t, true) // Publish with detailed summary and buildinfo. // Build project @@ -190,7 +190,7 @@ func TestGoPublishWithDeploymentView(t *testing.T) { wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") - prepareGoProject("project1", "", t, true) + prepareGoProject("project1", t, true) jfrogCli := tests.NewJfrogCli(execMain, "jf", "") err = execGo(jfrogCli, "gp", "v1.1.1") if err != nil { @@ -209,7 +209,7 @@ func TestGoVcsFallback(t *testing.T) { wd, err := os.Getwd() assert.NoError(t, err, "Failed to get current dir") - _ = prepareGoProject("vcsfallback", "", t, false) + _ = prepareGoProject("vcsfallback", t, false) jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") // Run "go get github.com/octocat/Hello-World" with --no-fallback. @@ -225,17 +225,14 @@ func TestGoVcsFallback(t *testing.T) { clientTestUtils.ChangeDirAndAssert(t, wd) } -func prepareGoProject(projectName, configDestDir string, t *testing.T, copyDirs bool) string { +func prepareGoProject(projectName string, t *testing.T, copyDirs bool) string { projectPath := createGoProject(t, projectName, copyDirs) testdataTarget := filepath.Join(tests.Out, "testdata") testdataSrc := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "go", "testdata") err := fileutils.CopyDir(testdataSrc, testdataTarget, copyDirs, nil) assert.NoError(t, err) - if configDestDir == "" { - configDestDir = filepath.Join(projectPath, ".jfrog") - } configFileDir := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "go", projectName, ".jfrog", "projects") - _, err = tests.ReplaceTemplateVariables(filepath.Join(configFileDir, "go.yaml"), filepath.Join(configDestDir, "projects")) + _, err = tests.ReplaceTemplateVariables(filepath.Join(configFileDir, "go.yaml"), filepath.Join(projectPath, ".jfrog", "projects")) assert.NoError(t, err) clientTestUtils.ChangeDirAndAssert(t, projectPath) log.Info("Using Go project located at", projectPath) diff --git a/gradle_test.go b/gradle_test.go index c89f8ca12..773521091 100644 --- a/gradle_test.go +++ b/gradle_test.go @@ -74,7 +74,8 @@ func TestGradleBuildWithServerID(t *testing.T) { createConfigFile(destPath, configFilePath, t) oldHomeDir := changeWD(t, filepath.Dir(buildGradlePath)) buildNumber := "1" - buildGradlePath = strings.Replace(buildGradlePath, `\`, "/", -1) // Windows compatibility. + // Windows compatibility + buildGradlePath = strings.ReplaceAll(buildGradlePath, `\`, "/") runJfrogCli(t, "gradle", "clean artifactoryPublish", "-b"+buildGradlePath, "--build-name="+tests.GradleBuildName, "--build-number="+buildNumber) clientTestUtils.ChangeDirAndAssert(t, oldHomeDir) // Validate @@ -106,7 +107,8 @@ func TestGradleBuildWithServerIDAndDetailedSummary(t *testing.T) { createConfigFile(destPath, configFilePath, t) oldHomeDir := changeWD(t, filepath.Dir(buildGradlePath)) buildNumber := "1" - buildGradlePath = strings.Replace(buildGradlePath, `\`, "/", -1) // Windows compatibility. + // Windows compatibility. + buildGradlePath = strings.ReplaceAll(buildGradlePath, `\`, "/") // Test gradle with detailed summary without buildinfo props. filteredGradleArgs := []string{"clean artifactoryPublish", "-b" + buildGradlePath} diff --git a/inttestutils/docker.go b/inttestutils/docker.go index 44f496d39..5b537d2db 100644 --- a/inttestutils/docker.go +++ b/inttestutils/docker.go @@ -51,7 +51,7 @@ func (image *BuildDockerImage) GetCmd() *exec.Cmd { } cmd = append(cmd, image.buildContext) - return exec.Command(image.containerManager.String(), cmd[:]...) + return exec.Command(image.containerManager.String(), cmd...) } func (image *BuildDockerImage) GetEnv() map[string]string { @@ -82,7 +82,7 @@ func (e *ExecDockerImage) GetCmd() *exec.Cmd { var cmd []string cmd = append(cmd, "exec") cmd = append(cmd, e.Args...) - return exec.Command(e.containerManager.String(), cmd[:]...) + return exec.Command(e.containerManager.String(), cmd...) } func (e *ExecDockerImage) GetEnv() map[string]string { @@ -118,7 +118,7 @@ func (run *RunDockerImage) GetCmd() *exec.Cmd { var cmd []string cmd = append(cmd, "run") cmd = append(cmd, run.Args...) - return exec.Command(run.containerManager.String(), cmd[:]...) + return exec.Command(run.containerManager.String(), cmd...) } func (run *RunDockerImage) GetEnv() map[string]string { @@ -147,7 +147,7 @@ func (image *DeleteDockerImage) GetCmd() *exec.Cmd { cmd = append(cmd, "image") cmd = append(cmd, "rm") cmd = append(cmd, image.imageTag) - return exec.Command(image.containerManager.String(), cmd[:]...) + return exec.Command(image.containerManager.String(), cmd...) } func (image *DeleteDockerImage) GetEnv() map[string]string { @@ -176,7 +176,7 @@ func (image *DeleteContainer) GetCmd() *exec.Cmd { cmd = append(cmd, "rm") cmd = append(cmd, "--force") cmd = append(cmd, image.containerName) - return exec.Command(image.containerManager.String(), cmd[:]...) + return exec.Command(image.containerManager.String(), cmd...) } func (image *DeleteContainer) GetEnv() map[string]string { diff --git a/main.go b/main.go index ddb09b4d8..8bf2d8e1c 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "golang.org/x/exp/slices" "os" "runtime" "sort" @@ -231,7 +232,7 @@ func getCommands() []cli.Command { return cisetupcommand.RunCiSetupCmd() }, }, - //{ + // { // Name: "invite", // Usage: invite.GetDescription(), // HelpName: corecommon.CreateUsage("invite", invite.GetDescription(), invite.Usage), @@ -241,24 +242,20 @@ func getCommands() []cli.Command { // Action: func(c *cli.Context) error { // return invitecommand.RunInviteCmd(c) // }, - //}, + // }, { Name: "setup", HideHelp: true, Hidden: true, Flags: cliutils.GetCommandFlags(cliutils.Setup), - Action: func(c *cli.Context) error { - return SetupCmd(c) - }, + Action: SetupCmd, }, { Name: "intro", HideHelp: true, Hidden: true, Flags: cliutils.GetCommandFlags(cliutils.Intro), - Action: func(*cli.Context) error { - return IntroCmd() - }, + Action: IntroCmd, }, { Name: cliutils.CmdOptions, @@ -269,7 +266,7 @@ func getCommands() []cli.Command { }, }, } - allCommands := append(cliNameSpaces, utils.GetPlugins()...) + allCommands := append(slices.Clone(cliNameSpaces), utils.GetPlugins()...) allCommands = append(allCommands, scan.GetCommands()...) allCommands = append(allCommands, buildtools.GetCommands()...) return append(allCommands, buildtools.GetBuildToolsHelpCommands()...) diff --git a/missioncontrol/cli.go b/missioncontrol/cli.go index ed7c22458..4e7a6341a 100644 --- a/missioncontrol/cli.go +++ b/missioncontrol/cli.go @@ -31,9 +31,7 @@ func GetCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), Aliases: []string{"la"}, BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return licenseAcquire(c) - }, + Action: licenseAcquire, }, { Name: "license-deploy", @@ -44,9 +42,7 @@ func GetCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), Aliases: []string{"ld"}, BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return licenseDeploy(c) - }, + Action: licenseDeploy, }, { Name: "license-release", @@ -57,9 +53,7 @@ func GetCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), Aliases: []string{"lr"}, BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return licenseRelease(c) - }, + Action: licenseRelease, }, { Name: "jpd-add", @@ -70,9 +64,7 @@ func GetCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), Aliases: []string{"ja"}, BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return jpdAdd(c) - }, + Action: jpdAdd, }, { Name: "jpd-delete", @@ -83,9 +75,7 @@ func GetCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), Aliases: []string{"jd"}, BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return jpdDelete(c) - }, + Action: jpdDelete, }, }) } diff --git a/nuget_test.go b/nuget_test.go index 446ee82a0..b77f106b5 100644 --- a/nuget_test.go +++ b/nuget_test.go @@ -15,6 +15,7 @@ import ( clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/exp/slices" "os" "path/filepath" "strconv" @@ -62,7 +63,7 @@ func TestDotnetResolve(t *testing.T) { func testNativeNugetDotnetResolve(t *testing.T, uniqueTests []testDescriptor, buildName string, projectType utils.ProjectType) { initNugetTest(t) - testDescriptors := append(uniqueTests, []testDescriptor{ + testDescriptors := append(slices.Clone(uniqueTests), []testDescriptor{ {"referencewithoutmodulechnage", "reference", []string{projectType.String(), "restore"}, []string{"reference"}, []int{6}}, {"referencewithmodulechnage", "reference", []string{projectType.String(), "restore", "--module=" + ModuleNameJFrogTest}, []string{ModuleNameJFrogTest}, []int{6}}, {"multireferencewithoutmodulechnage", "multireference", []string{projectType.String(), "restore"}, []string{"proj1", "proj2"}, []int{5, 3}}, diff --git a/pipelines/cli.go b/pipelines/cli.go index d01011e1c..b9c539250 100644 --- a/pipelines/cli.go +++ b/pipelines/cli.go @@ -29,9 +29,7 @@ func GetCommands() []cli.Command { HelpName: corecommon.CreateUsage("pl status", status.GetDescription(), status.Usage), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return fetchLatestPipelineRunStatus(c) - }, + Action: fetchLatestPipelineRunStatus, }, { Name: "trigger", @@ -42,9 +40,7 @@ func GetCommands() []cli.Command { UsageText: trigger.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return triggerNewRun(c) - }, + Action: triggerNewRun, }, { Name: "version", @@ -53,9 +49,7 @@ func GetCommands() []cli.Command { Usage: version.GetDescription(), HelpName: corecommon.CreateUsage("pl version", version.GetDescription(), version.Usage), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return getVersion(c) - }, + Action: getVersion, }, { Name: "sync", @@ -66,9 +60,7 @@ func GetCommands() []cli.Command { UsageText: sync.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return syncPipelineResources(c) - }, + Action: syncPipelineResources, }, { Name: "sync-status", @@ -78,9 +70,7 @@ func GetCommands() []cli.Command { HelpName: corecommon.CreateUsage("pl sync-status", syncstatus.GetDescription(), syncstatus.Usage), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return getSyncPipelineResourcesStatus(c) - }, + Action: getSyncPipelineResourcesStatus, }, }) } diff --git a/plugins/cli.go b/plugins/cli.go index 040027990..ae1842e4e 100644 --- a/plugins/cli.go +++ b/plugins/cli.go @@ -21,9 +21,7 @@ func GetCommands() []cli.Command { UsageText: installdocs.GetArguments(), ArgsUsage: common.CreateEnvVars(installdocs.EnvVar...), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return commands.InstallCmd(c) - }, + Action: commands.InstallCmd, }, { Name: "uninstall", @@ -33,9 +31,7 @@ func GetCommands() []cli.Command { UsageText: uninstalldocs.GetArguments(), ArgsUsage: common.CreateEnvVars(), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return commands.UninstallCmd(c) - }, + Action: commands.UninstallCmd, }, { Name: "publish", @@ -45,9 +41,7 @@ func GetCommands() []cli.Command { UsageText: publishdocs.GetArguments(), ArgsUsage: common.CreateEnvVars(publishdocs.EnvVar...), BashComplete: corecommon.CreateBashCompletionFunc(), - Action: func(c *cli.Context) error { - return commands.PublishCmd(c) - }, + Action: commands.PublishCmd, }, }) } diff --git a/plugins_test.go b/plugins_test.go index c1cd56828..83e51eb77 100644 --- a/plugins_test.go +++ b/plugins_test.go @@ -49,13 +49,13 @@ func TestPluginInstallUninstallOfficialRegistry(t *testing.T) { jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") // Try installing a plugin with specific version. - err = installAndAssertPlugin(t, jfrogCli, officialPluginForTest, officialPluginVersion) + err = installAndAssertPlugin(t, jfrogCli, officialPluginVersion) if err != nil { return } // Try installing the latest version of the plugin. Also verifies replacement was successful. - err = installAndAssertPlugin(t, jfrogCli, officialPluginForTest, "") + err = installAndAssertPlugin(t, jfrogCli, "") if err != nil { return } @@ -99,21 +99,21 @@ func TestPluginInstallWithProgressBar(t *testing.T) { jfrogCli := tests.NewJfrogCli(execMain, "jfrog", "") // Try installing a plugin with specific version. - err = installAndAssertPlugin(t, jfrogCli, officialPluginForTest, officialPluginVersion) + err = installAndAssertPlugin(t, jfrogCli, officialPluginVersion) if err != nil { return } // Try installing the latest version of the plugin. Also verifies replacement was successful. - err = installAndAssertPlugin(t, jfrogCli, officialPluginForTest, "") + err = installAndAssertPlugin(t, jfrogCli, "") if err != nil { return } } -func installAndAssertPlugin(t *testing.T, jfrogCli *tests.JfrogCli, pluginName, pluginVersion string) error { +func installAndAssertPlugin(t *testing.T, jfrogCli *tests.JfrogCli, pluginVersion string) error { // If version required, concat to plugin name - identifier := pluginName + identifier := officialPluginForTest if pluginVersion != "" { identifier += "@" + pluginVersion } @@ -124,7 +124,7 @@ func installAndAssertPlugin(t *testing.T, jfrogCli *tests.JfrogCli, pluginName, assert.NoError(t, err) return err } - err = verifyPluginInPluginsDir(t, pluginName, true, false) + err = verifyPluginInPluginsDir(t, officialPluginForTest, true, false) if err != nil { return err } diff --git a/scan/cli.go b/scan/cli.go index 115e619d0..a407a0519 100644 --- a/scan/cli.go +++ b/scan/cli.go @@ -182,12 +182,11 @@ func AuditCmd(c *cli.Context) error { allTechnologies := coreutils.GetAllTechnologiesList() technologies := []string{} for _, tech := range allTechnologies { - techExists := false - switch tech { - case coreutils.Maven: + var techExists bool + if tech == coreutils.Maven { // On Maven we use '--mvn' flag techExists = c.Bool("mvn") - default: + } else { techExists = c.Bool(tech.ToString()) } if techExists { @@ -215,7 +214,7 @@ func CurationCmd(c *cli.Context) error { return err } curationAuditCommand := curation.NewCurationAuditCommand(). - SetWorkingDirs(splitAndTrim(c.String("working-dirs"), ",")). + SetWorkingDirs(splitByCommaAndTrim(c.String("working-dirs"))). SetParallelRequests(threads) serverDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, true, "rt") @@ -264,11 +263,11 @@ func createGenericAuditCmd(c *cli.Context) (*audit.GenericAuditCommand, error) { SetFixableOnly(c.Bool(cliutils.FixableOnly)) if c.String("watches") != "" { - auditCmd.SetWatches(splitAndTrim(c.String("watches"), ",")) + auditCmd.SetWatches(splitByCommaAndTrim(c.String("watches"))) } if c.String("working-dirs") != "" { - auditCmd.SetWorkingDirs(splitAndTrim(c.String("working-dirs"), ",")) + auditCmd.SetWorkingDirs(splitByCommaAndTrim(c.String("working-dirs"))) } auditCmd.SetServerDetails(serverDetails). SetExcludeTestDependencies(c.Bool(cliutils.ExcludeTestDeps)). @@ -295,11 +294,11 @@ func ScanCmd(c *cli.Context) error { var specFile *spec.SpecFiles if c.IsSet("spec") { specFile, err = cliutils.GetFileSystemSpec(c) + if err != nil { + return err + } } else { - specFile, err = createDefaultScanSpec(c, addTrailingSlashToRepoPathIfNeeded(c)) - } - if err != nil { - return err + specFile = createDefaultScanSpec(c, addTrailingSlashToRepoPathIfNeeded(c)) } err = spec.ValidateSpec(specFile.Files, false, false) if err != nil { @@ -332,7 +331,7 @@ func ScanCmd(c *cli.Context) error { SetFixableOnly(c.Bool(cliutils.FixableOnly)). SetMinSeverityFilter(minSeverity) if c.String("watches") != "" { - scanCmd.SetWatches(splitAndTrim(c.String("watches"), ",")) + scanCmd.SetWatches(splitByCommaAndTrim(c.String("watches"))) } return commands.Exec(scanCmd) } @@ -410,7 +409,7 @@ func DockerScan(c *cli.Context, image string) error { SetFixableOnly(c.Bool(cliutils.FixableOnly)). SetMinSeverityFilter(minSeverity) if c.String("watches") != "" { - containerScanCommand.SetWatches(splitAndTrim(c.String("watches"), ",")) + containerScanCommand.SetWatches(splitByCommaAndTrim(c.String("watches"))) } return progressbar.ExecWithProgress(containerScanCommand) } @@ -424,7 +423,7 @@ func addTrailingSlashToRepoPathIfNeeded(c *cli.Context) string { return repoPath } -func createDefaultScanSpec(c *cli.Context, defaultTarget string) (*spec.SpecFiles, error) { +func createDefaultScanSpec(c *cli.Context, defaultTarget string) *spec.SpecFiles { return spec.NewBuilder(). Pattern(c.Args().Get(0)). Target(defaultTarget). @@ -433,7 +432,7 @@ func createDefaultScanSpec(c *cli.Context, defaultTarget string) (*spec.SpecFile Regexp(c.Bool("regexp")). Ant(c.Bool("ant")). IncludeDirs(c.Bool("include-dirs")). - BuildSpec(), nil + BuildSpec() } func createServerDetailsWithConfigOffer(c *cli.Context) (*coreconfig.ServerDetails, error) { @@ -466,8 +465,8 @@ func isProjectProvided(c *cli.Context) bool { return c.String("project") != "" || os.Getenv(coreutils.Project) != "" } -func splitAndTrim(paramValue, separator string) (res []string) { - args := strings.Split(paramValue, separator) +func splitByCommaAndTrim(paramValue string) (res []string) { + args := strings.Split(paramValue, ",") res = make([]string, len(args)) for i, arg := range args { res[i] = strings.TrimSpace(arg) diff --git a/transfer_test.go b/transfer_test.go index f3334ae53..bfae8a364 100644 --- a/transfer_test.go +++ b/transfer_test.go @@ -489,12 +489,12 @@ func updateDockerRepoParams(t *testing.T, targetServicesManager artifactory.Arti params.AllowAnyHostAuth = inverseBooleanPointer(params.AllowAnyHostAuth) params.EnableCookieManagement = inverseBooleanPointer(params.EnableCookieManagement) params.BypassHeadRequests = inverseBooleanPointer(params.BypassHeadRequests) - params.SocketTimeoutMillis = params.SocketTimeoutMillis + 100 - params.RetrievalCachePeriodSecs = params.RetrievalCachePeriodSecs + 100 - params.MetadataRetrievalTimeoutSecs = params.MetadataRetrievalTimeoutSecs + 100 - params.MissedRetrievalCachePeriodSecs = params.MissedRetrievalCachePeriodSecs + 100 - params.UnusedArtifactsCleanupPeriodHours = params.UnusedArtifactsCleanupPeriodHours + 100 - params.AssumedOfflinePeriodSecs = params.AssumedOfflinePeriodSecs + 100 + params.SocketTimeoutMillis += 100 + params.RetrievalCachePeriodSecs += 100 + params.MetadataRetrievalTimeoutSecs += 100 + params.MissedRetrievalCachePeriodSecs += 100 + params.UnusedArtifactsCleanupPeriodHours += 100 + params.AssumedOfflinePeriodSecs += 100 params.Username = "test123" params.ContentSynchronisation.Enabled = inverseBooleanPointer(params.ContentSynchronisation.Enabled) @@ -570,6 +570,6 @@ func updateProjectParams(t *testing.T, projectParams *accessServices.Project, ta projectParams.Description = "123123123123" projectParams.AdminPrivileges.IndexResources = &trueValue projectParams.SoftLimit = &trueValue - projectParams.StorageQuotaBytes = projectParams.StorageQuotaBytes + 1 + projectParams.StorageQuotaBytes += 1 assert.NoError(t, targetAccessManager.UpdateProject(accessServices.ProjectParams{ProjectDetails: *projectParams})) } diff --git a/utils/cliutils/utils.go b/utils/cliutils/utils.go index 41fb661d8..887af601b 100644 --- a/utils/cliutils/utils.go +++ b/utils/cliutils/utils.go @@ -821,9 +821,6 @@ func shouldCheckLatestCliVersion() (shouldCheck bool, err error) { func getLatestCliVersionFromGithubAPI() (githubVersionInfo githubResponse, err error) { client := &http.Client{Timeout: time.Second * 2} - if errorutils.CheckError(err) != nil { - return - } req, err := http.NewRequest(http.MethodGet, "https://api.github.com/repos/jfrog/jfrog-cli/releases/latest", nil) if errorutils.CheckError(err) != nil { return diff --git a/utils/progressbar/filesprogressbar.go b/utils/progressbar/filesprogressbar.go index 57997bedc..5046c7058 100644 --- a/utils/progressbar/filesprogressbar.go +++ b/utils/progressbar/filesprogressbar.go @@ -69,7 +69,7 @@ func (p *filesProgressBarManager) NewProgressReader(total int64, label, path str p.barsRWMutex.Lock() defer p.barsRWMutex.Unlock() p.barsWg.Add(1) - newBar := p.container.New(int64(total), + newBar := p.container.New(total, mpb.BarStyle().Lbound("|").Filler("🟩").Tip("🟩").Padding("⬛").Refiller("").Rbound("|"), mpb.BarRemoveOnComplete(), mpb.AppendDecorators( @@ -89,8 +89,7 @@ func (p *filesProgressBarManager) NewProgressReader(total int64, label, path str // Changes progress indicator state and acts accordingly. func (p *filesProgressBarManager) SetProgressState(id int, state string) { - switch state { - case "Merging": + if state == "Merging" { p.addNewMergingSpinner(id) } } diff --git a/utils/progressbar/readerprogressbar.go b/utils/progressbar/readerprogressbar.go index e44cab22b..19f396794 100644 --- a/utils/progressbar/readerprogressbar.go +++ b/utils/progressbar/readerprogressbar.go @@ -27,6 +27,7 @@ func (p *ReaderProgressBar) Abort() { } // GetId Returns the ProgressBar ID +//nolint:gocritic func (p *ReaderProgressBar) GetId() (Id int) { return p.Id } diff --git a/utils/progressbar/simpleprogressbar.go b/utils/progressbar/simpleprogressbar.go index 7387265bd..85e816306 100644 --- a/utils/progressbar/simpleprogressbar.go +++ b/utils/progressbar/simpleprogressbar.go @@ -9,7 +9,7 @@ type SimpleProgressBar struct { Id int } -// Usesd to update the progress bar progress. +// Used to update the progress bar progress. func (p *SimpleProgressBar) ActionWithProgress(reader io.Reader) (results io.Reader) { p.bar.Increment() return nil @@ -21,6 +21,7 @@ func (p *SimpleProgressBar) Abort() { } // GetId Returns the ProgressBar ID +//nolint:gocritic func (p *SimpleProgressBar) GetId() (Id int) { return p.Id } diff --git a/utils/summary/summary.go b/utils/summary/summary.go index c7a7624a1..bb9207d2b 100644 --- a/utils/summary/summary.go +++ b/utils/summary/summary.go @@ -79,9 +79,7 @@ func (bis *BuildInfoSummary) AddSha256(sha256Str string) { func GetSummaryReport(success, failed int, failNoOp bool, err error) *Summary { summary := &Summary{Totals: &Totals{}} - if err != nil || failed > 0 { - summary.Status = Failure - } else if success == 0 && failNoOp { + if err != nil || failed > 0 || (success == 0 && failNoOp) { summary.Status = Failure } else { summary.Status = Success diff --git a/utils/tests/consts.go b/utils/tests/consts.go index 7e13132e6..23c5202c9 100644 --- a/utils/tests/consts.go +++ b/utils/tests/consts.go @@ -1910,7 +1910,7 @@ func GetUploadedFileWithDownloadedPlaceHolder() []string { func GetFileWithDownloadedPlaceHolder() []string { return []string{ - filepath.Join(Out), + Out, filepath.Join(Out, "mypath2"), filepath.Join(Out, "mypath2", "b1.in"), filepath.Join(Out, "mypath2", "b2.in"), @@ -1932,7 +1932,7 @@ func GetUploadedFileWithDownloadedDoublePlaceHolder() []string { func GetFileWithDownloadedDoublePlaceHolder() []string { return []string{ - filepath.Join(Out), + Out, filepath.Join(Out, "mypath2"), filepath.Join(Out, "mypath2", "c"), filepath.Join(Out, "mypath2", "c", "c1.in"), @@ -1954,7 +1954,7 @@ func GetUploadedFileWithDownloadedPlaceHolderlashSlashSuffix() []string { func GetFileWithDownloadedPlaceHolderSlashSuffix() []string { return []string{ - filepath.Join(Out), + Out, filepath.Join(Out, "mypath2"), filepath.Join(Out, "mypath2", "b1.in"), filepath.Join(Out, "mypath2", "b2.in"), @@ -1972,12 +1972,12 @@ func GetFileWithDownloadedPlaceHolderSlashSuffix() []string { } } -func GetExpectedUploadSummaryDetails(RtUrl string) []clientutils.FileTransferDetails { +func GetExpectedUploadSummaryDetails(rtUrl string) []clientutils.FileTransferDetails { path1, path2, path3 := filepath.Join("testdata", "a", "a1.in"), filepath.Join("testdata", "a", "a2.in"), filepath.Join("testdata", "a", "a3.in") return []clientutils.FileTransferDetails{ - {SourcePath: path1, RtUrl: RtUrl, TargetPath: RtRepo1 + "/testdata/a/a1.in", Sha256: "4eb341b5d2762a853d79cc25e622aa8b978eb6e12c3259e2d99dc9dc60d82c5d"}, - {SourcePath: path2, RtUrl: RtUrl, TargetPath: RtRepo1 + "/testdata/a/a2.in", Sha256: "3e3deb6628658a48cf0d280a2210211f9d977ec2e10a4619b95d5fb85cb10450"}, - {SourcePath: path3, RtUrl: RtUrl, TargetPath: RtRepo1 + "/testdata/a/a3.in", Sha256: "14e3dc4749bf42df13a67a271065b0f334d0ad36bb34a74cc57c6e137f9af09e"}, + {SourcePath: path1, RtUrl: rtUrl, TargetPath: RtRepo1 + "/testdata/a/a1.in", Sha256: "4eb341b5d2762a853d79cc25e622aa8b978eb6e12c3259e2d99dc9dc60d82c5d"}, + {SourcePath: path2, RtUrl: rtUrl, TargetPath: RtRepo1 + "/testdata/a/a2.in", Sha256: "3e3deb6628658a48cf0d280a2210211f9d977ec2e10a4619b95d5fb85cb10450"}, + {SourcePath: path3, RtUrl: rtUrl, TargetPath: RtRepo1 + "/testdata/a/a3.in", Sha256: "14e3dc4749bf42df13a67a271065b0f334d0ad36bb34a74cc57c6e137f9af09e"}, } } diff --git a/utils/tests/container.go b/utils/tests/container.go index 7894cea76..05024b0f1 100644 --- a/utils/tests/container.go +++ b/utils/tests/container.go @@ -3,12 +3,10 @@ package tests import ( "context" "fmt" - "io" - "testing" - "github.com/jfrog/jfrog-client-go/utils/log" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" + "io" ) // When two containers are joined to the same network, one container is able to address another by using its name (as the hostname). @@ -55,14 +53,14 @@ func NewContainerRequest() *ContainerRequest { // rather than using a pre-built image. // This setter cannot be used with 'SetImage' to run a container.. // -// context - The path to the context of of the docker build +// context - The path to the context of the docker build // file - The path from the context to the Dockerfile for the image, defaults to "Dockerfile" // BuildArgs - Args to docker daemon -func (c *ContainerRequest) SetDockerfile(context, file string, BuildArgs map[string]*string) *ContainerRequest { +func (c *ContainerRequest) SetDockerfile(context, file string, buildArgs map[string]*string) *ContainerRequest { c.request.FromDockerfile = testcontainers.FromDockerfile{ Context: context, Dockerfile: file, - BuildArgs: BuildArgs, + BuildArgs: buildArgs, PrintBuildLog: true, } return c @@ -123,7 +121,7 @@ func (c *ContainerRequest) WaitFor(waitingFor wait.Strategy) *ContainerRequest { } // Creates a container based on container request parameters. -func (c *ContainerRequest) Build(ctx context.Context, t *testing.T, autoStart bool) (*TestContainer, error) { +func (c *ContainerRequest) Build(ctx context.Context, autoStart bool) (*TestContainer, error) { container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: c.request, Started: autoStart, diff --git a/utils/tests/proxy/server/server.go b/utils/tests/proxy/server/server.go index 308ae0930..2462e5d75 100644 --- a/utils/tests/proxy/server/server.go +++ b/utils/tests/proxy/server/server.go @@ -86,7 +86,7 @@ func copyHeaders(dst, src http.Header) { func httpProxyHandler(w http.ResponseWriter, r *http.Request) { if r.RequestURI == "/" { - w.WriteHeader(200) + w.WriteHeader(http.StatusOK) } else { removeProxyHeaders(r) t := &http.Transport{} @@ -118,7 +118,7 @@ type testProxy struct { func (t *testProxy) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request) { if request.RequestURI == "/" { - responseWriter.WriteHeader(200) + responseWriter.WriteHeader(http.StatusOK) } else { host := request.URL.Host request.Host = "https://" + request.Host diff --git a/utils/tests/utils.go b/utils/tests/utils.go index bd16fa265..5f245f63e 100644 --- a/utils/tests/utils.go +++ b/utils/tests/utils.go @@ -605,7 +605,7 @@ func ReplaceTemplateVariables(path, destPath string) (string, error) { } for name, value := range getSubstitutionMap() { - content = bytes.Replace(content, []byte(name), []byte(value), -1) + content = bytes.ReplaceAll(content, []byte(name), []byte(value)) } if destPath == "" { destPath, err = os.Getwd() @@ -620,7 +620,7 @@ func ReplaceTemplateVariables(path, destPath string) (string, error) { } specPath := filepath.Join(destPath, filepath.Base(path)) log.Info("Creating spec file at:", specPath) - err = os.WriteFile(specPath, []byte(content), 0700) + err = os.WriteFile(specPath, content, 0700) if err != nil { return "", errorutils.CheckError(err) } diff --git a/xray_test.go b/xray_test.go index 0496b5d23..b469c9568 100644 --- a/xray_test.go +++ b/xray_test.go @@ -96,7 +96,7 @@ func TestXrayBinaryScanJson(t *testing.T) { func TestXrayBinaryScanSimpleJson(t *testing.T) { output := testXrayBinaryScan(t, string(utils.SimpleJson)) - verifySimpleJsonScanResults(t, output, 0, 0, 1, 1) + verifySimpleJsonScanResults(t, output, 1, 1) } func TestXrayBinaryScanJsonWithProgress(t *testing.T) { @@ -110,7 +110,7 @@ func TestXrayBinaryScanSimpleJsonWithProgress(t *testing.T) { callback := tests.MockProgressInitialization() defer callback() output := testXrayBinaryScan(t, string(utils.SimpleJson)) - verifySimpleJsonScanResults(t, output, 0, 0, 1, 1) + verifySimpleJsonScanResults(t, output, 1, 1) } func testXrayBinaryScan(t *testing.T, format string) string { @@ -144,7 +144,7 @@ func TestXrayAuditNpmJson(t *testing.T) { func TestXrayAuditNpmSimpleJson(t *testing.T) { output := testXrayAuditNpm(t, string(utils.SimpleJson)) - verifySimpleJsonScanResults(t, output, 0, 0, 1, 1) + verifySimpleJsonScanResults(t, output, 1, 1) } func testXrayAuditNpm(t *testing.T, format string) string { @@ -173,7 +173,7 @@ func TestXrayAuditYarnJson(t *testing.T) { func TestXrayAuditYarnSimpleJson(t *testing.T) { testXrayAuditYarn(t, "yarn", func() { output := runXrayAuditYarnWithOutput(t, string(utils.SimpleJson)) - verifySimpleJsonScanResults(t, output, 0, 0, 1, 1) + verifySimpleJsonScanResults(t, output, 1, 1) }) } @@ -212,7 +212,7 @@ func TestXrayAuditNugetJson(t *testing.T) { func TestXrayAuditNugetSimpleJson(t *testing.T) { output := testXrayAuditNuget(t, "single", string(utils.SimpleJson)) - verifySimpleJsonScanResults(t, output, 0, 0, 2, 0) + verifySimpleJsonScanResults(t, output, 2, 0) } // Tests NuGet audit by providing a multi-project NuGet project and asserts any error. @@ -244,7 +244,7 @@ func TestXrayAuditGradleJson(t *testing.T) { func TestXrayAuditGradleSimpleJson(t *testing.T) { output := testXrayAuditGradle(t, string(utils.SimpleJson)) - verifySimpleJsonScanResults(t, output, 0, 0, 0, 0) + verifySimpleJsonScanResults(t, output, 0, 0) } func testXrayAuditGradle(t *testing.T, format string) string { @@ -268,7 +268,7 @@ func TestXrayAuditMavenJson(t *testing.T) { func TestXrayAuditMavenSimpleJson(t *testing.T) { output := testXrayAuditMaven(t, string(utils.SimpleJson)) - verifySimpleJsonScanResults(t, output, 0, 0, 1, 1) + verifySimpleJsonScanResults(t, output, 1, 1) } func testXrayAuditMaven(t *testing.T, format string) string { @@ -323,7 +323,7 @@ func TestXrayAuditMultiProjects(t *testing.T) { assert.NoError(t, fileutils.CopyDir(multiProject, tempDirPath, true, nil)) workingDirsFlag := fmt.Sprintf("--working-dirs=%s, %s ,%s", filepath.Join(tempDirPath, "maven"), filepath.Join(tempDirPath, "nuget", "single"), filepath.Join(tempDirPath, "python", "pip")) output := xrayCli.RunCliCmdWithOutput(t, "audit", "--format="+string(utils.SimpleJson), workingDirsFlag) - verifySimpleJsonScanResults(t, output, 0, 0, 30, 0) + verifySimpleJsonScanResults(t, output, 30, 0) } func TestXrayAuditPipJson(t *testing.T) { @@ -333,7 +333,7 @@ func TestXrayAuditPipJson(t *testing.T) { func TestXrayAuditPipSimpleJson(t *testing.T) { output := testXrayAuditPip(t, string(utils.SimpleJson), "") - verifySimpleJsonScanResults(t, output, 0, 0, 3, 1) + verifySimpleJsonScanResults(t, output, 3, 1) } func TestXrayAuditPipJsonWithRequirementsFile(t *testing.T) { @@ -343,7 +343,7 @@ func TestXrayAuditPipJsonWithRequirementsFile(t *testing.T) { func TestXrayAuditPipSimpleJsonWithRequirementsFile(t *testing.T) { output := testXrayAuditPip(t, string(utils.SimpleJson), "requirements.txt") - verifySimpleJsonScanResults(t, output, 0, 0, 2, 0) + verifySimpleJsonScanResults(t, output, 2, 0) } func testXrayAuditPip(t *testing.T, format, requirementsFile string) string { @@ -372,7 +372,7 @@ func TestXrayAuditPipenvJson(t *testing.T) { func TestXrayAuditPipenvSimpleJson(t *testing.T) { output := testXrayAuditPipenv(t, string(utils.SimpleJson)) - verifySimpleJsonScanResults(t, output, 0, 0, 3, 1) + verifySimpleJsonScanResults(t, output, 3, 1) } func testXrayAuditPipenv(t *testing.T, format string) string { @@ -434,7 +434,7 @@ func TestXrayAuditPoetryJson(t *testing.T) { func TestXrayAuditPoetrySimpleJson(t *testing.T) { output := testXrayAuditPoetry(t, string(utils.SimpleJson)) - verifySimpleJsonScanResults(t, output, 0, 0, 3, 1) + verifySimpleJsonScanResults(t, output, 3, 1) } func testXrayAuditPoetry(t *testing.T, format string) string { @@ -503,12 +503,10 @@ func verifyJsonScanResults(t *testing.T, content string, minViolations, minVulne } } -func verifySimpleJsonScanResults(t *testing.T, content string, minSecViolations, minLicViolations, minVulnerabilities, minLicenses int) { +func verifySimpleJsonScanResults(t *testing.T, content string, minVulnerabilities, minLicenses int) { var results formats.SimpleJsonResults err := json.Unmarshal([]byte(content), &results) if assert.NoError(t, err) { - assert.GreaterOrEqual(t, len(results.SecurityViolations), minSecViolations) - assert.GreaterOrEqual(t, len(results.LicensesViolations), minLicViolations) assert.GreaterOrEqual(t, len(results.Vulnerabilities), minVulnerabilities) assert.GreaterOrEqual(t, len(results.Licenses), minLicenses) } @@ -703,11 +701,13 @@ func TestCurationAudit(t *testing.T) { output := localXrayCli.RunCliCmdWithOutput(t, "curation-audit", "--format="+string(utils.Json), workingDirsFlag) expectedResp := getCurationExpectedResponse(config) var got []coreCuration.PackageStatus - err = json.Unmarshal([]byte(output[strings.Index(output, "["):]), &got) + bracketIndex := strings.Index(output, "[") + require.Less(t, 0, bracketIndex, "Unexpected Curation output with missing '['") + err = json.Unmarshal([]byte(output[bracketIndex:]), &got) assert.NoError(t, err) assert.Equal(t, expectedResp, got) for k, v := range expectedRequest { - assert.Truef(t, v, "didn't recieve expected GET request for packe url %s", k) + assert.Truef(t, v, "didn't receive expected GET request for package url %s", k) } } From e049aa0e3869787610b073091ecff110c836715c Mon Sep 17 00:00:00 2001 From: Yahav Itzhak Date: Sun, 18 Jun 2023 11:24:37 +0300 Subject: [PATCH 04/25] Update Go to 1.20.5 (#2032) --- Jenkinsfile | 2 +- build/docker/full/Dockerfile | 2 +- build/docker/slim/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index b06ee2698..ec5c772ef 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -25,7 +25,7 @@ node("docker") { repo = 'jfrog-cli' sh 'rm -rf temp' sh 'mkdir temp' - def goRoot = tool 'go-1.20.4' + def goRoot = tool 'go-1.20.5' env.GOROOT="$goRoot" env.PATH+=":${goRoot}/bin" env.GO111MODULE="on" diff --git a/build/docker/full/Dockerfile b/build/docker/full/Dockerfile index 76e3f5c69..6198ce57b 100644 --- a/build/docker/full/Dockerfile +++ b/build/docker/full/Dockerfile @@ -1,6 +1,6 @@ ARG repo_name_21 # Remove ${repo_name_21} to pull from Docker Hub. -FROM ${repo_name_21}/jfrog-docker/golang:1.20.4 as builder +FROM ${repo_name_21}/jfrog-docker/golang:1.20 as builder ARG image_name=jfrog-cli-full ARG cli_executable_name WORKDIR /${image_name} diff --git a/build/docker/slim/Dockerfile b/build/docker/slim/Dockerfile index b9d93b469..ae69bd4c7 100644 --- a/build/docker/slim/Dockerfile +++ b/build/docker/slim/Dockerfile @@ -1,6 +1,6 @@ ARG repo_name_21 # Remove ${repo_name_21} to pull from Docker Hub. -FROM ${repo_name_21}/jfrog-docker/golang:1.20.4-alpine as builder +FROM ${repo_name_21}/jfrog-docker/golang:1.20-alpine as builder ARG image_name=jfrog-cli ARG cli_executable_name WORKDIR /${image_name} From 65ed020a3d453e8723ab01c17c77e80d75069b03 Mon Sep 17 00:00:00 2001 From: Sara Omari <114062096+sarao1310@users.noreply.github.com> Date: Sun, 18 Jun 2023 22:02:55 +0300 Subject: [PATCH 05/25] Unreleased bug upload progress bar values (#2033) unreleased bug - fix upload progress bar values --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ce09de2c6..8ee26ff50 100644 --- a/go.mod +++ b/go.mod @@ -128,4 +128,4 @@ replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230614081045-ef833fcb4fdd +replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230618140310-d7dc9bc462c2 diff --git a/go.sum b/go.sum index 60006e5ce..31f1f4785 100644 --- a/go.sum +++ b/go.sum @@ -242,8 +242,8 @@ github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230613104333-33061fa53a01 h1:MvKxuFsgCeIL74qeXJ7Z6rbDO0tfE15M3D24U0kGgFs= github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230613104333-33061fa53a01/go.mod h1:Kzh4oTlJu1iYFNQcgAHgKIMvsvgC5LN2DlV/NHWCXZM= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230614081045-ef833fcb4fdd h1:/X2eIts0BRy3Y6AhzBnM+8Dmrl0assoBFG1iyW6Jq8U= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230614081045-ef833fcb4fdd/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230618140310-d7dc9bc462c2 h1:DtWbIgT1XZqodzwlVuGKj60XeKfdhGxIVIKy2MgXkm4= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230618140310-d7dc9bc462c2/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= From ec935850a1e67cecdef6163de6870f00fb49fbf1 Mon Sep 17 00:00:00 2001 From: Eyal Ben Moshe Date: Tue, 27 Jun 2023 21:12:22 +0300 Subject: [PATCH 06/25] Promote to version 2.41.0 (#2045) --- build/npm/v2-jf/package-lock.json | 2 +- build/npm/v2-jf/package.json | 2 +- build/npm/v2/package-lock.json | 2 +- build/npm/v2/package.json | 2 +- go.mod | 8 ++++---- go.sum | 10 ++++------ utils/cliutils/cli_consts.go | 2 +- 7 files changed, 13 insertions(+), 15 deletions(-) diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index 3ccfed708..aa6066ad8 100644 --- a/build/npm/v2-jf/package-lock.json +++ b/build/npm/v2-jf/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.40.0", + "version": "2.41.0", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index 4419ecaf0..c175df8ac 100644 --- a/build/npm/v2-jf/package.json +++ b/build/npm/v2-jf/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.40.0", + "version": "2.41.0", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/npm/v2/package-lock.json b/build/npm/v2/package-lock.json index 21d8687c0..931857fc7 100644 --- a/build/npm/v2/package-lock.json +++ b/build/npm/v2/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2", - "version": "2.40.0", + "version": "2.41.0", "lockfileVersion": 1 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index bd5cba97f..482eb14d1 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.40.0", + "version": "2.41.0", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/go.mod b/go.mod index 8ee26ff50..a15728c3f 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 github.com/jfrog/build-info-go v1.9.6 github.com/jfrog/gofrog v1.3.0 - github.com/jfrog/jfrog-cli-core/v2 v2.35.0 - github.com/jfrog/jfrog-client-go v1.30.0 + github.com/jfrog/jfrog-cli-core/v2 v2.36.1 + github.com/jfrog/jfrog-client-go v1.30.1 github.com/jszwec/csvutil v1.8.0 github.com/mholt/archiver/v3 v3.5.1 github.com/pkg/errors v0.9.1 @@ -124,8 +124,8 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230613104333-33061fa53a01 +// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230613104333-33061fa53a01 // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230618140310-d7dc9bc462c2 +// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230618140310-d7dc9bc462c2 diff --git a/go.sum b/go.sum index 31f1f4785..2671dc95b 100644 --- a/go.sum +++ b/go.sum @@ -109,8 +109,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= -github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= -github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v23.0.5+incompatible h1:DaxtlTJjFSnLOXVNUBU1+6kXGz2lpDoEAH6QoxaSg8k= @@ -240,10 +238,10 @@ github.com/jfrog/build-info-go v1.9.6 h1:lCJ2j5uXAlJsSwDe5J8WD7Co1f/hUlZvMfwfb5A github.com/jfrog/build-info-go v1.9.6/go.mod h1:GbuFS+viHCKZYx9nWHYu7ab1DgQkFdtVN3BJPUNb2D4= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230613104333-33061fa53a01 h1:MvKxuFsgCeIL74qeXJ7Z6rbDO0tfE15M3D24U0kGgFs= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230613104333-33061fa53a01/go.mod h1:Kzh4oTlJu1iYFNQcgAHgKIMvsvgC5LN2DlV/NHWCXZM= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230618140310-d7dc9bc462c2 h1:DtWbIgT1XZqodzwlVuGKj60XeKfdhGxIVIKy2MgXkm4= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230618140310-d7dc9bc462c2/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= +github.com/jfrog/jfrog-cli-core/v2 v2.36.1 h1:O67ovxouqXYljE2Lo890ytM9fDiYsMCZJ8F/DHdSY7w= +github.com/jfrog/jfrog-cli-core/v2 v2.36.1/go.mod h1:Wvf/XWVcRSu1ZuloLOofkifuM8BLZZ2LiYYzmdUn80Y= +github.com/jfrog/jfrog-client-go v1.30.1 h1:wASYBrFkpWzQHTNnCIIfqpDLtQF5oNcwQK9rrv8I8AA= +github.com/jfrog/jfrog-client-go v1.30.1/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index c8903a5aa..1bada4aa2 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -4,7 +4,7 @@ import "time" const ( // General CLI constants - CliVersion = "2.40.0" + CliVersion = "2.41.0" ClientAgent = "jfrog-cli-go" // CLI base commands constants: From f6fb5aafe466bf670600a73c94c27d4c550dc227 Mon Sep 17 00:00:00 2001 From: Michael Sverdlov Date: Wed, 28 Jun 2023 11:51:52 +0300 Subject: [PATCH 07/25] Fix 'jf intro' command (#2047) --- go.mod | 19 +++++++++---------- go.sum | 38 +++++++++++++++++++------------------- main.go | 2 +- main_test.go | 11 +++++++++++ 4 files changed, 40 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index a15728c3f..f93d7a975 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/agnivade/levenshtein v1.1.1 github.com/buger/jsonparser v1.1.1 github.com/go-git/go-git/v5 v5.7.0 - github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 + github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d github.com/jfrog/build-info-go v1.9.6 github.com/jfrog/gofrog v1.3.0 github.com/jfrog/jfrog-cli-core/v2 v2.36.1 @@ -15,19 +15,18 @@ require ( github.com/mholt/archiver/v3 v3.5.1 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.4 - github.com/testcontainers/testcontainers-go v0.20.1 - github.com/urfave/cli v1.22.12 + github.com/testcontainers/testcontainers-go v0.21.0 + github.com/urfave/cli v1.22.14 github.com/vbauerster/mpb/v7 v7.5.3 github.com/xeipuuv/gojsonschema v1.2.0 - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 - golang.org/x/term v0.8.0 + golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df + golang.org/x/term v0.9.0 gopkg.in/yaml.v2 v2.4.0 - ) require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect - github.com/BurntSushi/toml v1.2.1 // indirect + github.com/BurntSushi/toml v1.3.2 // indirect github.com/CycloneDX/cyclonedx-go v0.7.1 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230528122434-6f98819771a1 // indirect @@ -78,7 +77,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect - github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f // indirect + github.com/moby/term v0.5.0 // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/nwaples/rardecode v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect @@ -109,10 +108,10 @@ require ( github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect golang.org/x/crypto v0.9.0 // indirect - golang.org/x/mod v0.10.0 // indirect + golang.org/x/mod v0.11.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.8.0 // indirect + golang.org/x/sys v0.9.0 // indirect golang.org/x/text v0.9.0 // indirect google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect google.golang.org/grpc v1.52.0 // indirect diff --git a/go.sum b/go.sum index 2671dc95b..e6454b94f 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7 github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= +github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CycloneDX/cyclonedx-go v0.7.1 h1:5w1SxjGm9MTMNTuRbEPyw21ObdbaagTWF/KfF0qHTRE= github.com/CycloneDX/cyclonedx-go v0.7.1/go.mod h1:N/nrdWQI2SIjaACyyDs/u7+ddCkyl/zkNs8xFsHF2Ps= @@ -102,7 +102,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -147,8 +147,8 @@ github.com/go-git/go-git/v5 v5.7.0/go.mod h1:coJHKEOk5kUClpsNlXrUvPrDxY3w3gjHvhc github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027 h1:LCGzZb4kMUUjMUzLxxqSJBwo9szUO0tK8cOxnEOT4Jc= -github.com/gocarina/gocsv v0.0.0-20230406101422-6445c2b15027/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= +github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d h1:KbPOUXFUDJxwZ04vbmDOc3yuruGvVO+LOa7cVER3yWw= +github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -300,8 +300,8 @@ github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YO github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f h1:J/7hjLaHLD7epG0m6TBMGmp4NQ+ibBYLfeyJWdAIFLA= -github.com/moby/term v0.0.0-20221128092401-c43b287e0e0f/go.mod h1:15ce4BGCFxt7I5NQKT+HV0yEDxmf6fSysfEDiVo3zFM= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= @@ -381,14 +381,14 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/testcontainers/testcontainers-go v0.20.1 h1:mK15UPJ8c5P+NsQKmkqzs/jMdJt6JMs5vlw2y4j92c0= -github.com/testcontainers/testcontainers-go v0.20.1/go.mod h1:zb+NOlCQBkZ7RQp4QI+YMIHyO2CQ/qsXzNF5eLJ24SY= +github.com/testcontainers/testcontainers-go v0.21.0 h1:syePAxdeTzfkap+RrJaQZpJQ/s/fsUgn11xIvHrOE9U= +github.com/testcontainers/testcontainers-go v0.21.0/go.mod h1:c1ez3WVRHq7T/Aj+X3TIipFBwkBaNT5iNCY8+1b83Ng= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8= -github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= +github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= +github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= github.com/vbauerster/mpb/v7 v7.5.3 h1:BkGfmb6nMrrBQDFECR/Q7RkKCw7ylMetCb4079CGs4w= github.com/vbauerster/mpb/v7 v7.5.3/go.mod h1:i+h4QY6lmLvBNK2ah1fSreiw3ajskRlBp9AhY/PnuOE= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= @@ -442,8 +442,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df h1:UA2aFVmmsIlefxMk29Dp2juaUSth8Pyn3Tq5Y5mJGME= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -469,8 +469,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -597,15 +597,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= +golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= +golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/main.go b/main.go index 8bf2d8e1c..d7d904495 100644 --- a/main.go +++ b/main.go @@ -306,7 +306,7 @@ func SetupCmd(c *cli.Context) error { return envsetup.RunEnvSetupCmd(c, format) } -func IntroCmd() error { +func IntroCmd(_ *cli.Context) error { ci, err := clientutils.GetBoolEnvValue(coreutils.CI, false) if ci || err != nil { return err diff --git a/main_test.go b/main_test.go index 53c207ba1..7bab29827 100644 --- a/main_test.go +++ b/main_test.go @@ -330,3 +330,14 @@ func initDeploymentViewTest(t *testing.T) (assertDeploymentViewFunc func(), clea } return } + +func TestIntro(t *testing.T) { + buffer, _, previousLog := coreTests.RedirectLogOutputToBuffer() + defer clientlog.SetLogger(previousLog) + + setEnvCallBack := clientTestUtils.SetEnvWithCallbackAndAssert(t, "CI", "false") + defer setEnvCallBack() + + runJfrogCli(t, "intro") + assert.Contains(t, buffer.String(), "Thank you for installing version") +} From 06c272d398a9ebe55eaa8cb0c010bfd97170c1df Mon Sep 17 00:00:00 2001 From: Eyal Ben Moshe Date: Wed, 28 Jun 2023 23:37:44 +0300 Subject: [PATCH 08/25] Promote to version 2.41.1 (#2048) --- build/npm/v2-jf/package-lock.json | 2 +- build/npm/v2-jf/package.json | 2 +- build/npm/v2/package-lock.json | 2 +- build/npm/v2/package.json | 2 +- utils/cliutils/cli_consts.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index aa6066ad8..e7fe21f0e 100644 --- a/build/npm/v2-jf/package-lock.json +++ b/build/npm/v2-jf/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.41.0", + "version": "2.41.1", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index c175df8ac..ac8a5f918 100644 --- a/build/npm/v2-jf/package.json +++ b/build/npm/v2-jf/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.41.0", + "version": "2.41.1", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/npm/v2/package-lock.json b/build/npm/v2/package-lock.json index 931857fc7..439ff2702 100644 --- a/build/npm/v2/package-lock.json +++ b/build/npm/v2/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2", - "version": "2.41.0", + "version": "2.41.1", "lockfileVersion": 1 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index 482eb14d1..748eec5dd 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.41.0", + "version": "2.41.1", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index 1bada4aa2..ce9c0b1d2 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -4,7 +4,7 @@ import "time" const ( // General CLI constants - CliVersion = "2.41.0" + CliVersion = "2.41.1" ClientAgent = "jfrog-cli-go" // CLI base commands constants: From 33339adf607ab4353060ba7a9e771c6d6b7e8c7a Mon Sep 17 00:00:00 2001 From: Michael Sverdlov Date: Thu, 29 Jun 2023 16:09:31 +0300 Subject: [PATCH 09/25] Fix transfer settings issue (#2051) --- artifactory/cli.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artifactory/cli.go b/artifactory/cli.go index 6e35b64ad..a2a328e71 100644 --- a/artifactory/cli.go +++ b/artifactory/cli.go @@ -2388,7 +2388,7 @@ func getTransferIncludeExcludeProjects(c *cli.Context) (includeProjectsPatterns, return } -func transferSettingsCmd() error { +func transferSettingsCmd(_ *cli.Context) error { transferSettingsCmd := transfer.NewTransferSettingsCommand() return commands.Exec(transferSettingsCmd) } From 70915585b479ca66715111773809d433efeac877 Mon Sep 17 00:00:00 2001 From: Robi Nino Date: Thu, 29 Jun 2023 21:50:09 +0300 Subject: [PATCH 10/25] Add Support for Release Bundles Create and Promote (#1943) --- artifactory/cli.go | 19 +- artifactory/cli_test.go | 34 +-- artifactory_test.go | 2 +- distribution/cli.go | 12 +- docs/artifactory/releasebundlecreate/help.go | 2 +- docs/artifactory/releasebundledelete/help.go | 2 +- .../releasebundledistribute/help.go | 2 +- docs/artifactory/releasebundlesign/help.go | 2 +- docs/artifactory/releasebundleupdate/help.go | 2 +- docs/lifecycle/create/help.go | 15 + docs/lifecycle/promote/help.go | 18 ++ documentation/CLI-for-JFrog-Lifecycle.md | 133 +++++++++ documentation/cli.ftmap | 4 +- go.mod | 4 +- go.sum | 8 +- lifecycle/cli.go | 134 +++++++++ lifecycle/cli_test.go | 42 +++ lifecycle_test.go | 275 ++++++++++++++++++ main.go | 2 + main_test.go | 47 +-- maven_test.go | 30 +- testdata/dev_repo_repository_config.json | 6 + testdata/filespecs/search_all_prod_repo.json | 7 + testdata/filespecs/upload_dev_spec_a.json | 10 + testdata/filespecs/upload_dev_spec_b.json | 10 + testdata/filespecs/upload_dev_spec_c.json | 10 + testdata/lifecycle/builds-spec-1-2.json | 13 + testdata/lifecycle/builds-spec-3.json | 8 + testdata/lifecycle/keys/private.txt | 83 ++++++ testdata/lifecycle/keys/public.txt | 41 +++ testdata/lifecycle/release-bundles-spec.json | 12 + testdata/prod_repo_repository_config.json | 6 + utils/cliutils/commandsflags.go | 117 +++++--- utils/cliutils/utils.go | 18 +- utils/tests/consts.go | 71 ++--- utils/tests/utils.go | 43 +++ 36 files changed, 1074 insertions(+), 170 deletions(-) create mode 100644 docs/lifecycle/create/help.go create mode 100644 docs/lifecycle/promote/help.go create mode 100644 documentation/CLI-for-JFrog-Lifecycle.md create mode 100644 lifecycle/cli.go create mode 100644 lifecycle/cli_test.go create mode 100644 lifecycle_test.go create mode 100644 testdata/dev_repo_repository_config.json create mode 100644 testdata/filespecs/search_all_prod_repo.json create mode 100644 testdata/filespecs/upload_dev_spec_a.json create mode 100644 testdata/filespecs/upload_dev_spec_b.json create mode 100644 testdata/filespecs/upload_dev_spec_c.json create mode 100644 testdata/lifecycle/builds-spec-1-2.json create mode 100644 testdata/lifecycle/builds-spec-3.json create mode 100644 testdata/lifecycle/keys/private.txt create mode 100644 testdata/lifecycle/keys/public.txt create mode 100644 testdata/lifecycle/release-bundles-spec.json create mode 100644 testdata/prod_repo_repository_config.json diff --git a/artifactory/cli.go b/artifactory/cli.go index a2a328e71..11e7474c2 100644 --- a/artifactory/cli.go +++ b/artifactory/cli.go @@ -2412,7 +2412,7 @@ func createDefaultCopyMoveSpec(c *cli.Context) (*spec.SpecFiles, error) { Props(c.String("props")). ExcludeProps(c.String("exclude-props")). Build(c.String("build")). - Project(getProject(c)). + Project(cliutils.GetProject(c)). ExcludeArtifacts(c.Bool("exclude-artifacts")). IncludeDeps(c.Bool("include-deps")). Bundle(c.String("bundle")). @@ -2439,7 +2439,7 @@ func createDefaultDeleteSpec(c *cli.Context) (*spec.SpecFiles, error) { Props(c.String("props")). ExcludeProps(c.String("exclude-props")). Build(c.String("build")). - Project(getProject(c)). + Project(cliutils.GetProject(c)). ExcludeArtifacts(c.Bool("exclude-artifacts")). IncludeDeps(c.Bool("include-deps")). Bundle(c.String("bundle")). @@ -2463,7 +2463,7 @@ func createDefaultSearchSpec(c *cli.Context) (*spec.SpecFiles, error) { Props(c.String("props")). ExcludeProps(c.String("exclude-props")). Build(c.String("build")). - Project(getProject(c)). + Project(cliutils.GetProject(c)). ExcludeArtifacts(c.Bool("exclude-artifacts")). IncludeDeps(c.Bool("include-deps")). Bundle(c.String("bundle")). @@ -2490,7 +2490,7 @@ func createDefaultPropertiesSpec(c *cli.Context) (*spec.SpecFiles, error) { Props(c.String("props")). ExcludeProps(c.String("exclude-props")). Build(c.String("build")). - Project(getProject(c)). + Project(cliutils.GetProject(c)). ExcludeArtifacts(c.Bool("exclude-artifacts")). IncludeDeps(c.Bool("include-deps")). Bundle(c.String("bundle")). @@ -2586,7 +2586,7 @@ func createDefaultDownloadSpec(c *cli.Context) (*spec.SpecFiles, error) { Props(c.String("props")). ExcludeProps(c.String("exclude-props")). Build(c.String("build")). - Project(getProject(c)). + Project(cliutils.GetProject(c)). ExcludeArtifacts(c.Bool("exclude-artifacts")). IncludeDeps(c.Bool("include-deps")). Bundle(c.String("bundle")). @@ -2722,12 +2722,3 @@ func getOffsetAndLimitValues(c *cli.Context) (offset, limit int, err error) { return } - -// Get project key from flag or environment variable -func getProject(c *cli.Context) string { - project := c.String("project") - if project == "" { - project = os.Getenv(coreutils.Project) - } - return project -} diff --git a/artifactory/cli_test.go b/artifactory/cli_test.go index fb848c0d4..e951be591 100644 --- a/artifactory/cli_test.go +++ b/artifactory/cli_test.go @@ -2,15 +2,12 @@ package artifactory import ( "bytes" - "flag" "github.com/jfrog/jfrog-cli-core/v2/common/spec" - "path/filepath" - "strings" - "testing" - "github.com/jfrog/jfrog-cli/utils/tests" "github.com/stretchr/testify/assert" "github.com/urfave/cli" + "path/filepath" + "testing" ) func TestPrepareSearchDownloadDeleteCommands(t *testing.T) { @@ -34,7 +31,7 @@ func TestPrepareSearchDownloadDeleteCommands(t *testing.T) { for _, test := range testRuns { t.Run(test.name, func(t *testing.T) { - context, buffer := createContext(t, test.flags, test.args) + context, buffer := tests.CreateContext(t, test.flags, test.args) funcArray := []func(c *cli.Context) (*spec.SpecFiles, error){ prepareSearchCommand, prepareDownloadCommand, prepareDeleteCommand, } @@ -67,7 +64,7 @@ func TestPrepareCopyMoveCommand(t *testing.T) { for _, test := range testRuns { t.Run(test.name, func(t *testing.T) { - context, buffer := createContext(t, test.flags, test.args) + context, buffer := tests.CreateContext(t, test.flags, test.args) specFiles, err := prepareCopyMoveCommand(context) assertGenericCommand(t, err, buffer, test.expectError, test.expectedPattern, test.expectedBuild, test.expectedBundle, specFiles) }) @@ -96,7 +93,7 @@ func TestPreparePropsCmd(t *testing.T) { for _, test := range testRuns { t.Run(test.name, func(t *testing.T) { - context, buffer := createContext(t, test.flags, test.args) + context, buffer := tests.CreateContext(t, test.flags, test.args) propsCommand, err := preparePropsCmd(context) var actualSpec *spec.SpecFiles if propsCommand != nil { @@ -119,27 +116,6 @@ func assertGenericCommand(t *testing.T, err error, buffer *bytes.Buffer, expectE } } -func createContext(t *testing.T, testFlags, testArgs []string) (*cli.Context, *bytes.Buffer) { - flagSet := createFlagSet(t, testFlags, testArgs) - app := cli.NewApp() - app.Writer = &bytes.Buffer{} - return cli.NewContext(app, flagSet, nil), &bytes.Buffer{} -} - func getSpecPath(spec string) string { return filepath.Join("..", "testdata", "filespecs", spec) } - -// Create flag set with input flags and arguments. -func createFlagSet(t *testing.T, flags []string, args []string) *flag.FlagSet { - flagSet := flag.NewFlagSet("TestFlagSet", flag.ContinueOnError) - flags = append(flags, "url=http://127.0.0.1:8081/artifactory") - var cmdFlags []string - for _, curFlag := range flags { - flagSet.String(strings.Split(curFlag, "=")[0], "", "") - cmdFlags = append(cmdFlags, "--"+curFlag) - } - cmdFlags = append(cmdFlags, args...) - assert.NoError(t, flagSet.Parse(cmdFlags)) - return flagSet -} diff --git a/artifactory_test.go b/artifactory_test.go index 250545b05..9a5fbe194 100644 --- a/artifactory_test.go +++ b/artifactory_test.go @@ -4549,7 +4549,7 @@ func validateArtifactoryVersion(t *testing.T, minVersion string) { return } if !rtVersion.AtLeast(minVersion) { - t.Skip("Skipping artifactory project test. Artifactory version not supported.") + t.Skip("Skipping test. Artifactory version not supported.") } } diff --git a/distribution/cli.go b/distribution/cli.go index 81d04c537..682156767 100644 --- a/distribution/cli.go +++ b/distribution/cli.go @@ -28,7 +28,7 @@ func GetCommands() []cli.Command { return cliutils.GetSortedCommands(cli.CommandsByName{ { Name: "release-bundle-create", - Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleCreate), + Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleV1Create), Aliases: []string{"rbc"}, Usage: releasebundlecreate.GetDescription(), HelpName: coreCommonDocs.CreateUsage("ds rbc", releasebundlecreate.GetDescription(), releasebundlecreate.Usage), @@ -39,7 +39,7 @@ func GetCommands() []cli.Command { }, { Name: "release-bundle-update", - Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleUpdate), + Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleV1Update), Aliases: []string{"rbu"}, Usage: releasebundleupdate.GetDescription(), HelpName: coreCommonDocs.CreateUsage("ds rbu", releasebundleupdate.GetDescription(), releasebundleupdate.Usage), @@ -50,7 +50,7 @@ func GetCommands() []cli.Command { }, { Name: "release-bundle-sign", - Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleSign), + Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleV1Sign), Aliases: []string{"rbs"}, Usage: releasebundlesign.GetDescription(), HelpName: coreCommonDocs.CreateUsage("ds rbs", releasebundlesign.GetDescription(), releasebundlesign.Usage), @@ -61,7 +61,7 @@ func GetCommands() []cli.Command { }, { Name: "release-bundle-distribute", - Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleDistribute), + Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleV1Distribute), Aliases: []string{"rbd"}, Usage: releasebundledistribute.GetDescription(), HelpName: coreCommonDocs.CreateUsage("ds rbd", releasebundledistribute.GetDescription(), releasebundledistribute.Usage), @@ -72,7 +72,7 @@ func GetCommands() []cli.Command { }, { Name: "release-bundle-delete", - Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleDelete), + Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleV1Delete), Aliases: []string{"rbdel"}, Usage: releasebundledelete.GetDescription(), HelpName: coreCommonDocs.CreateUsage("ds rbdel", releasebundledelete.GetDescription(), releasebundledelete.Usage), @@ -328,7 +328,7 @@ func populateReleaseNotesSyntax(c *cli.Context) (distributionServicesUtils.Relea return distributionServicesUtils.PlainText, errorutils.CheckErrorf("--release-notes-syntax must be one of: markdown, asciidoc or plain_text.") } } - // If the file extension is ".md" or ".markdown", use the markdown syntax + // If the file extension is ".md" or ".markdown", use the Markdown syntax extension := strings.ToLower(filepath.Ext(c.String("release-notes-path"))) if extension == ".md" || extension == ".markdown" { return distributionServicesUtils.Markdown, nil diff --git a/docs/artifactory/releasebundlecreate/help.go b/docs/artifactory/releasebundlecreate/help.go index 5448b96ed..91df44ceb 100644 --- a/docs/artifactory/releasebundlecreate/help.go +++ b/docs/artifactory/releasebundlecreate/help.go @@ -4,7 +4,7 @@ var Usage = []string{"ds rbc [command options] [command options] "} func GetDescription() string { - return "Create a release bundle." + return "Create a release bundle v1." } func GetArguments() string { diff --git a/docs/artifactory/releasebundledelete/help.go b/docs/artifactory/releasebundledelete/help.go index ce377d18b..ec9e1fe7a 100644 --- a/docs/artifactory/releasebundledelete/help.go +++ b/docs/artifactory/releasebundledelete/help.go @@ -3,7 +3,7 @@ package releasebundledelete var Usage = []string{"ds rbdel [command options] "} func GetDescription() string { - return "Delete a release bundle." + return "Delete a release bundle v1." } func GetArguments() string { diff --git a/docs/artifactory/releasebundledistribute/help.go b/docs/artifactory/releasebundledistribute/help.go index 0fe5459ec..b277a84d3 100644 --- a/docs/artifactory/releasebundledistribute/help.go +++ b/docs/artifactory/releasebundledistribute/help.go @@ -3,7 +3,7 @@ package releasebundledistribute var Usage = []string{"ds rbd [command options] "} func GetDescription() string { - return "Distribute a release bundle." + return "Distribute a release bundle v1." } func GetArguments() string { diff --git a/docs/artifactory/releasebundlesign/help.go b/docs/artifactory/releasebundlesign/help.go index d576353a6..977874bd8 100644 --- a/docs/artifactory/releasebundlesign/help.go +++ b/docs/artifactory/releasebundlesign/help.go @@ -3,7 +3,7 @@ package releasebundlesign var Usage = []string{"ds rbs [command options] "} func GetDescription() string { - return "Sign a release bundle." + return "Sign a release bundle v1." } func GetArguments() string { diff --git a/docs/artifactory/releasebundleupdate/help.go b/docs/artifactory/releasebundleupdate/help.go index 0f80fc4af..d7cd5541f 100644 --- a/docs/artifactory/releasebundleupdate/help.go +++ b/docs/artifactory/releasebundleupdate/help.go @@ -4,7 +4,7 @@ var Usage = []string{"ds rbu [command options] [command options] "} func GetDescription() string { - return "Updates an existing unsigned release bundle version." + return "Updates an existing unsigned release bundle v1 version." } func GetArguments() string { diff --git a/docs/lifecycle/create/help.go b/docs/lifecycle/create/help.go new file mode 100644 index 000000000..c7079e3f2 --- /dev/null +++ b/docs/lifecycle/create/help.go @@ -0,0 +1,15 @@ +package create + +var Usage = []string{"rbc [command options] "} + +func GetDescription() string { + return "Create a release bundle from builds or from existing release bundles" +} + +func GetArguments() string { + return ` release bundle name + Name of the newly created Release Bundle. + + release bundle version + Version of the newly created Release Bundle.` +} diff --git a/docs/lifecycle/promote/help.go b/docs/lifecycle/promote/help.go new file mode 100644 index 000000000..b4954a8cf --- /dev/null +++ b/docs/lifecycle/promote/help.go @@ -0,0 +1,18 @@ +package promote + +var Usage = []string{"rbp [command options] "} + +func GetDescription() string { + return "Promote a release bundle" +} + +func GetArguments() string { + return ` release bundle name + Name of the Release Bundle to promote. + + release bundle version + Version of the Release Bundle to promote. + + environment + Name of the target environment for the promotion.` +} diff --git a/documentation/CLI-for-JFrog-Lifecycle.md b/documentation/CLI-for-JFrog-Lifecycle.md new file mode 100644 index 000000000..f81b7c817 --- /dev/null +++ b/documentation/CLI-for-JFrog-Lifecycle.md @@ -0,0 +1,133 @@ +JFrog CLI : CLI for JFrog Release Lifecycle Management +====================================== + + +Overview +-------- + +This page describes how to use JFrog CLI with [JFrog Release Lifecycle Management](https://jfrog.com/help/r/jfrog-artifactory-documentation/jfrog-release-lifecycle-management-solution). + +Read more about JFrog CLI [here](https://jfrog.com/help/r/jfrog-cli). + +--- +**Note** +> JFrog Release Lifecycle Management is only available since [Artifactory 7.63.2](https://jfrog.com/help/r/jfrog-release-information/artifactory-7.63.2-cloud). +--- + +### Syntax + +When used with JFrog Release Lifecycle Management, JFrog CLI uses the following syntax: + + $ jf command-name global-options command-options arguments + +### Commands + +The following sections describe the commands available in JFrog CLI for use with JFrog Release Lifecycle Management. + +### Creating a release bundle from builds or from existing release bundles + +This commands allows creating a release bundle from one of two sources: +1. Published build infos. To use, provide the `--builds` option, which accepts a path to a JSON file of the following syntax: + ```json + { + "builds": [ + { + "name": "build name", + "number": "build number", + "project": "project" + } + ] + } + ``` + `number` is optional, latest build will be used if empty. + + `project` is optional, default project will be used if empty. + +2. Existing release bundles. To use, provide the `--release-bundles` option, which accepts a path to a JSON file of the following syntax: + ```json + { + "releaseBundles": [ + { + "name": "release bundle name", + "version": "release bundle version", + "project": "project" + } + ] + } + ``` + `project` is optional, default project will be used if empty. + +| | | +|------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Command-name | release-bundle-create | +| Abbreviation | rbc | +| Command options | | +| --builds | \[Optional\]

Path to a JSON file containing information of the source builds from which to create a release bundle. | +| --project | \[Optional\]

Project key associated with the Release Bundle version. | +| --release-bundles | \[Optional\]

Path to a JSON file containing information of the source release bundles from which to create a release bundle. | +| --server-id | \[Optional\]

Platform server ID configured using the config command. | +| --signing-key | \[Mandatory\]

The GPG/RSA key-pair name given in Artifactory. | +| --sync | \[Default: false\]

Set to true to run synchronously. | +| Command arguments | | +| release bundle name | Name of the newly created Release Bundle. | +| release bundle version | Version of the newly created Release Bundle. | + +##### Examples + +##### Example 1 + +Create a release bundle with name "myApp" and version "1.0.0", with signing key pair "myKeyPair". +The release bundle will include artifacts of the builds that were provided in the builds spec. + + jf rbc --builds=/path/to/builds-spec.json --signing-key=myKeyPair myApp 1.0.0 + +##### Example 2 + +Create a release bundle with name "myApp" and version "1.0.0", with signing key pair "myKeyPair". +The release bundle will include artifacts of the release bundles that were provided in the release bundles spec. + + jf ds rbc --spec=/path/to/release-bundles-spec.json --signing-key=myKeyPair myApp 1.0.0 + +##### Example 3 + +Create a release bundle synchronously with name "myApp" and version "1.0.0", in project "project0", with signing key pair "myKeyPair". +The release bundle will include artifacts of the release bundles that were provided in the release bundles spec. + + jf ds rbc --spec=/path/to/release-bundles-spec.json --signing-key=myKeyPair --sync=true --project=project0 myApp 1.0.0 + +### Promoting a release bundle + +This commands allows promoting a release bundle to a target environment. + +| | | +|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Command-name | release-bundle-promote | +| Abbreviation | rbp | +| Command options | | +| --overwrite | \[Default: false\]

Set to true to replace artifacts with the same name but a different checksum if such already exist at the promotion targets. By default, the promotion is stopped in a case of such conflict | +| --project | \[Optional\]

Project key associated with the Release Bundle version. | +| --server-id | \[Optional\]

Platform server ID configured using the config command. | +| --signing-key | \[Mandatory\]

The GPG/RSA key-pair name given in Artifactory. | +| --sync | \[Default: false\]

Set to true to run synchronously. | +| Command arguments | | +| release bundle name | Name of the Release Bundle to promote. | +| release bundle version | Version of the Release Bundle to promote. | +| environment | Name of the target environment for the promotion. | + + +##### Examples + +##### Example 1 + +Promote a release bundle named "myApp" version "1.0.0" to environment "PROD". +Use signing key pair "myKeyPair". + + jf rbp --signing-key=myKeyPair myApp 1.0.0 PROD + +##### Example 2 + +Promote a release bundle synchronously to environment "PROD". +The release bundle is named "myApp", version "1.0.0", of project "project0". +Use signing key pair "myKeyPair" and overwrite at conflict. + + jf rbp --signing-key=myKeyPair --project=project0 --overwrite=true --sync=true myApp 1.0.0 PROD diff --git a/documentation/cli.ftmap b/documentation/cli.ftmap index 8a14c4de4..2a967949b 100644 --- a/documentation/cli.ftmap +++ b/documentation/cli.ftmap @@ -13,6 +13,8 @@ - + + + diff --git a/go.mod b/go.mod index f93d7a975..c516a946e 100644 --- a/go.mod +++ b/go.mod @@ -123,8 +123,8 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230613104333-33061fa53a01 +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230629184314-ff61ffffba34 // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230618140310-d7dc9bc462c2 +replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230629174113-81715f46ec0f diff --git a/go.sum b/go.sum index e6454b94f..6e5785091 100644 --- a/go.sum +++ b/go.sum @@ -238,10 +238,10 @@ github.com/jfrog/build-info-go v1.9.6 h1:lCJ2j5uXAlJsSwDe5J8WD7Co1f/hUlZvMfwfb5A github.com/jfrog/build-info-go v1.9.6/go.mod h1:GbuFS+viHCKZYx9nWHYu7ab1DgQkFdtVN3BJPUNb2D4= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.36.1 h1:O67ovxouqXYljE2Lo890ytM9fDiYsMCZJ8F/DHdSY7w= -github.com/jfrog/jfrog-cli-core/v2 v2.36.1/go.mod h1:Wvf/XWVcRSu1ZuloLOofkifuM8BLZZ2LiYYzmdUn80Y= -github.com/jfrog/jfrog-client-go v1.30.1 h1:wASYBrFkpWzQHTNnCIIfqpDLtQF5oNcwQK9rrv8I8AA= -github.com/jfrog/jfrog-client-go v1.30.1/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230629184314-ff61ffffba34 h1:i1nENbEtG6uv5V92UacU6okTW3zcH1VfzmkvJn9nK7Y= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230629184314-ff61ffffba34/go.mod h1:zc3la+URXmlEvrDhcY2g4AnnAQPOsmJisVfJZM06o+g= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230629174113-81715f46ec0f h1:FzagM0DDnwhcOCR+/grBwrg625a8mwOdytnJTlGCkAI= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230629174113-81715f46ec0f/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/lifecycle/cli.go b/lifecycle/cli.go new file mode 100644 index 000000000..8caa332d2 --- /dev/null +++ b/lifecycle/cli.go @@ -0,0 +1,134 @@ +package lifecycle + +import ( + "errors" + "github.com/jfrog/jfrog-cli-core/v2/common/commands" + coreCommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" + "github.com/jfrog/jfrog-cli-core/v2/lifecycle" + coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-cli/docs/common" + rbCreate "github.com/jfrog/jfrog-cli/docs/lifecycle/create" + rbPromote "github.com/jfrog/jfrog-cli/docs/lifecycle/promote" + "github.com/jfrog/jfrog-cli/utils/cliutils" + "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-client-go/utils/errorutils" + "github.com/urfave/cli" +) + +const lcCategory = "Lifecycle" + +func GetCommands() []cli.Command { + return cliutils.GetSortedCommands(cli.CommandsByName{ + { + Name: "release-bundle-create", + Aliases: []string{"rbc"}, + Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundleCreate), + Usage: rbCreate.GetDescription(), + HelpName: coreCommon.CreateUsage("release-bundle-create", rbCreate.GetDescription(), rbCreate.Usage), + UsageText: rbCreate.GetArguments(), + ArgsUsage: common.CreateEnvVars(), + BashComplete: coreCommon.CreateBashCompletionFunc(), + Category: lcCategory, + Action: create, + }, + { + Name: "release-bundle-promote", + Aliases: []string{"rbp"}, + Flags: cliutils.GetCommandFlags(cliutils.ReleaseBundlePromote), + Usage: rbPromote.GetDescription(), + HelpName: coreCommon.CreateUsage("release-bundle-promote", rbPromote.GetDescription(), rbPromote.Usage), + UsageText: rbPromote.GetArguments(), + ArgsUsage: common.CreateEnvVars(), + BashComplete: coreCommon.CreateBashCompletionFunc(), + Category: lcCategory, + Action: promote, + }, + }) +} + +func validateCreateReleaseBundleContext(c *cli.Context) error { + if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil { + return err + } + + if c.NArg() != 2 { + return cliutils.WrongNumberOfArgumentsHandler(c) + } + + if err := assertSigningKeyProvided(c); err != nil { + return err + } + + bothProvided := c.IsSet(cliutils.Builds) && c.IsSet(cliutils.ReleaseBundles) + noneProvided := !c.IsSet(cliutils.Builds) && !c.IsSet(cliutils.ReleaseBundles) + if bothProvided || noneProvided { + return errorutils.CheckErrorf("exactly one of the following options must be supplied: --%s or --%s", cliutils.Builds, cliutils.ReleaseBundles) + } + return nil +} + +func create(c *cli.Context) (err error) { + if err = validateCreateReleaseBundleContext(c); err != nil { + return err + } + + lcDetails, err := createLifecycleDetailsByFlags(c) + if err != nil { + return + } + + createCmd := lifecycle.NewReleaseBundleCreate().SetServerDetails(lcDetails).SetReleaseBundleName(c.Args().Get(0)). + SetReleaseBundleVersion(c.Args().Get(1)).SetSigningKeyName(c.String(cliutils.SigningKey)).SetSync(c.Bool(cliutils.Sync)). + SetReleaseBundleProject(cliutils.GetProject(c)).SetBuildsSpecPath(c.String(cliutils.Builds)). + SetReleaseBundlesSpecPath(c.String(cliutils.ReleaseBundles)) + return commands.Exec(createCmd) +} + +func promote(c *cli.Context) error { + if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil { + return err + } + + if c.NArg() != 3 { + return cliutils.WrongNumberOfArgumentsHandler(c) + } + + if err := assertSigningKeyProvided(c); err != nil { + return err + } + + lcDetails, err := createLifecycleDetailsByFlags(c) + if err != nil { + return err + } + + createCmd := lifecycle.NewReleaseBundlePromote().SetServerDetails(lcDetails).SetReleaseBundleName(c.Args().Get(0)). + SetReleaseBundleVersion(c.Args().Get(1)).SetEnvironment(c.Args().Get(2)).SetSigningKeyName(c.String(cliutils.SigningKey)). + SetSync(c.Bool(cliutils.Sync)).SetReleaseBundleProject(cliutils.GetProject(c)).SetOverwrite(c.Bool(cliutils.Overwrite)) + return commands.Exec(createCmd) +} + +func assertSigningKeyProvided(c *cli.Context) error { + if c.String(cliutils.SigningKey) == "" { + return errorutils.CheckErrorf("the --%s option is mandatory", cliutils.SigningKey) + } + return nil +} + +func createLifecycleDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { + lcDetails, err := cliutils.CreateServerDetailsWithConfigOffer(c, false, cliutils.Platform) + if err != nil { + return nil, err + } + if lcDetails.Url == "" { + return nil, errors.New("platform URL is mandatory for lifecycle commands") + } + PlatformToLifecycleUrls(lcDetails) + return lcDetails, nil +} + +func PlatformToLifecycleUrls(lcDetails *coreConfig.ServerDetails) { + lcDetails.ArtifactoryUrl = utils.AddTrailingSlashIfNeeded(lcDetails.Url) + "artifactory/" + lcDetails.LifecycleUrl = utils.AddTrailingSlashIfNeeded(lcDetails.Url) + "lifecycle/" + lcDetails.Url = "" +} diff --git a/lifecycle/cli_test.go b/lifecycle/cli_test.go new file mode 100644 index 000000000..9da70f718 --- /dev/null +++ b/lifecycle/cli_test.go @@ -0,0 +1,42 @@ +package lifecycle + +import ( + "github.com/jfrog/jfrog-cli/utils/cliutils" + "github.com/jfrog/jfrog-cli/utils/tests" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestValidateCreateReleaseBundleContext(t *testing.T) { + testRuns := []struct { + name string + args []string + flags []string + expectError bool + }{ + {"withoutArgs", []string{}, []string{}, true}, + {"oneArg", []string{"one"}, []string{}, true}, + {"twoArgs", []string{"one", "two"}, []string{}, true}, + {"extraArgs", []string{"one", "two", "three", "four"}, []string{}, true}, + {"bothSources", []string{"one", "two", "three"}, []string{cliutils.Builds + "=/path/to/file", cliutils.ReleaseBundles + "=/path/to/file"}, true}, + {"noSources", []string{"one", "two", "three"}, []string{}, true}, + {"builds without signing key", []string{"name", "version"}, []string{cliutils.Builds + "=/path/to/file"}, true}, + {"builds correct", []string{"name", "version"}, []string{ + cliutils.Builds + "=/path/to/file", cliutils.SigningKey + "=key"}, false}, + {"releaseBundles without signing key", []string{"name", "version", "env"}, []string{cliutils.ReleaseBundles + "=/path/to/file"}, true}, + {"releaseBundles", []string{"name", "version"}, []string{ + cliutils.ReleaseBundles + "=/path/to/file", cliutils.SigningKey + "=key"}, false}, + } + + for _, test := range testRuns { + t.Run(test.name, func(t *testing.T) { + context, buffer := tests.CreateContext(t, test.flags, test.args) + err := validateCreateReleaseBundleContext(context) + if test.expectError { + assert.Error(t, err, buffer) + } else { + assert.NoError(t, err, buffer) + } + }) + } +} diff --git a/lifecycle_test.go b/lifecycle_test.go new file mode 100644 index 000000000..24980c734 --- /dev/null +++ b/lifecycle_test.go @@ -0,0 +1,275 @@ +package main + +import ( + "encoding/json" + "fmt" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + configUtils "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli/inttestutils" + lifecycleCli "github.com/jfrog/jfrog-cli/lifecycle" + "github.com/jfrog/jfrog-cli/utils/cliutils" + "github.com/jfrog/jfrog-cli/utils/tests" + "github.com/jfrog/jfrog-client-go/http/httpclient" + "github.com/jfrog/jfrog-client-go/lifecycle" + "github.com/jfrog/jfrog-client-go/lifecycle/services" + clientUtils "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-client-go/utils/errorutils" + "github.com/stretchr/testify/assert" + "net/http" + "os" + "path/filepath" + "testing" +) + +const ( + rbMinVersion = "7.45.0" + gpgKeyPairName = "lc-tests-key-pair" + lcTestdataPath = "lifecycle" + releaseBundlesSpec = "release-bundles-spec.json" + buildsSpec12 = "builds-spec-1-2.json" + buildsSpec3 = "builds-spec-3.json" + prodEnvironment = "PROD" + number1, number2, number3 = "111", "222", "333" +) + +var ( + lcDetails *configUtils.ServerDetails + lcCli *tests.JfrogCli +) + +func TestLifecycle(t *testing.T) { + initLifecycleTest(t) + defer cleanLifecycleTests(t) + lcManager := getLcServiceManager(t) + + // Upload builds to create release bundles from. + deleteBuilds := uploadBuilds(t) + defer deleteBuilds() + + // Create release bundles from builds synchronously. + createRb(t, buildsSpec12, cliutils.Builds, tests.LcRbName1, number1, true) + defer deleteReleaseBundle(t, lcManager, tests.LcRbName1, number1) + + // Create release bundles from builds asynchronously and assert status. + createRb(t, buildsSpec3, cliutils.Builds, tests.LcRbName2, number2, false) + defer deleteReleaseBundle(t, lcManager, tests.LcRbName2, number2) + assertStatusCompleted(t, lcManager, tests.LcRbName2, number2, "") + + // Create a combined release bundle from the two previous release bundle. + createRb(t, releaseBundlesSpec, cliutils.ReleaseBundles, tests.LcRbName3, number3, true) + defer deleteReleaseBundle(t, lcManager, tests.LcRbName3, number3) + + // Promote the last release bundle. + promoteRb(t, lcManager, number3) + + // Verify the artifacts of both the initial release bundles made it to the prod repo. + searchSpec, err := tests.CreateSpec(tests.SearchAllProdRepo) + assert.NoError(t, err) + inttestutils.VerifyExistInArtifactory(tests.GetExpectedLifecycleArtifacts(), searchSpec, serverDetails, t) +} + +func uploadBuilds(t *testing.T) func() { + uploadBuild(t, tests.UploadDevSpecA, tests.LcBuildName1, number1) + uploadBuild(t, tests.UploadDevSpecB, tests.LcBuildName2, number2) + uploadBuild(t, tests.UploadDevSpecC, tests.LcBuildName3, number3) + return func() { + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.LcBuildName1, artHttpDetails) + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.LcBuildName2, artHttpDetails) + inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, tests.LcBuildName3, artHttpDetails) + } +} + +func createRb(t *testing.T, specName, sourceOption, buildName, buildNumber string, sync bool) { + specFile, err := getSpecFile(specName) + assert.NoError(t, err) + argsAndOptions := []string{ + "rbc", + buildName, + buildNumber, + getOption(sourceOption, specFile), + getOption(cliutils.SigningKey, gpgKeyPairName), + } + // Add the --sync option only if requested, to test the default value. + if sync { + argsAndOptions = append(argsAndOptions, getOption(cliutils.Sync, "true")) + } + assert.NoError(t, lcCli.Exec(argsAndOptions...)) +} + +func getOption(option, value string) string { + return fmt.Sprintf("--%s=%s", option, value) +} + +func promoteRb(t *testing.T, lcManager *lifecycle.LifecycleServicesManager, rbVersion string) { + output := lcCli.RunCliCmdWithOutput(t, "rbp", tests.LcRbName3, rbVersion, prodEnvironment, + getOption(cliutils.SigningKey, gpgKeyPairName), + getOption(cliutils.Overwrite, "true"), + "--project=default") + var promotionResp services.RbPromotionResp + if !assert.NoError(t, json.Unmarshal([]byte(output), &promotionResp)) { + return + } + assertStatusCompleted(t, lcManager, tests.LcRbName3, rbVersion, promotionResp.CreatedMillis.String()) +} + +func getSpecFile(fileName string) (string, error) { + source := filepath.Join(tests.GetTestResourcesPath(), lcTestdataPath, fileName) + return tests.ReplaceTemplateVariables(source, "") +} + +// If createdMillis is provided, assert status for promotion. If blank, assert for creation. +func assertStatusCompleted(t *testing.T, lcManager *lifecycle.LifecycleServicesManager, rbName, rbVersion, createdMillis string) { + resp, err := getStatus(lcManager, rbName, rbVersion, createdMillis) + if !assert.NoError(t, err) { + return + } + assert.Equal(t, services.Completed, resp.Status) +} + +func getLcServiceManager(t *testing.T) *lifecycle.LifecycleServicesManager { + lcManager, err := utils.CreateLifecycleServiceManager(lcDetails, false) + assert.NoError(t, err) + return lcManager +} + +func authenticateLifecycle() string { + *tests.JfrogUrl = clientUtils.AddTrailingSlashIfNeeded(*tests.JfrogUrl) + lcDetails = &configUtils.ServerDetails{ + Url: *tests.JfrogUrl} + lifecycleCli.PlatformToLifecycleUrls(lcDetails) + + cred := fmt.Sprintf("--url=%s", *tests.JfrogUrl) + if *tests.JfrogAccessToken != "" { + lcDetails.AccessToken = *tests.JfrogAccessToken + cred += fmt.Sprintf(" --access-token=%s", lcDetails.AccessToken) + } else { + lcDetails.User = *tests.JfrogUser + lcDetails.Password = *tests.JfrogPassword + cred += fmt.Sprintf(" --user=%s --password=%s", lcDetails.User, lcDetails.Password) + } + return cred +} + +func getStatus(lcManager *lifecycle.LifecycleServicesManager, rbName, rbVersion, createdMillis string) (services.ReleaseBundleStatusResponse, error) { + rbDetails := services.ReleaseBundleDetails{ + ReleaseBundleName: rbName, + ReleaseBundleVersion: rbVersion, + } + + if createdMillis == "" { + return lcManager.GetReleaseBundleCreationStatus(rbDetails, "", true) + } + return lcManager.GetReleaseBundlePromotionStatus(rbDetails, "", createdMillis, true) +} + +func deleteReleaseBundle(t *testing.T, lcManager *lifecycle.LifecycleServicesManager, rbName, rbVersion string) { + rbDetails := services.ReleaseBundleDetails{ + ReleaseBundleName: rbName, + ReleaseBundleVersion: rbVersion, + } + + assert.NoError(t, lcManager.DeleteReleaseBundle(rbDetails, services.ReleaseBundleQueryParams{Async: false})) +} + +func uploadBuild(t *testing.T, specFileName, buildName, buildNumber string) { + specFile, err := tests.CreateSpec(specFileName) + assert.NoError(t, err) + runRt(t, "upload", "--spec="+specFile, "--build-name="+buildName, "--build-number="+buildNumber) + runRt(t, "build-publish", buildName, buildNumber) +} + +func initLifecycleTest(t *testing.T) { + if !*tests.TestLifecycle { + t.Skip("Skipping lifecycle test. To run release bundle test add the '-test.lc=true' option.") + } + validateArtifactoryVersion(t, rbMinVersion) + + if !isLifecycleSupported(t) { + t.Skip("Skipping lifecycle test because the functionality is not enabled on the provided JPD.") + } +} + +func isLifecycleSupported(t *testing.T) (skip bool) { + client, err := httpclient.ClientBuilder().Build() + assert.NoError(t, err) + + resp, _, _, err := client.SendGet(serverDetails.ArtifactoryUrl+"api/release_bundles/records/non-existing-rb", true, artHttpDetails, "") + if !assert.NoError(t, err) { + return + } + return resp.StatusCode != http.StatusNotImplemented +} + +func InitLifecycleTests() { + initArtifactoryCli() + initLifecycleCli() + cleanUpOldBuilds() + cleanUpOldRepositories() + cleanUpOldUsers() + tests.AddTimestampToGlobalVars() + createRequiredRepos() + sendGpgKeyPair() +} + +func initLifecycleCli() { + if lcCli != nil { + return + } + lcCli = tests.NewJfrogCli(execMain, "jfrog", authenticateLifecycle()) +} + +func CleanLifecycleTests() { + deleteCreatedRepos() +} + +func cleanLifecycleTests(t *testing.T) { + deleteFilesFromRepo(t, tests.RtDevRepo) + deleteFilesFromRepo(t, tests.RtProdRepo) + tests.CleanFileSystem() +} + +func sendGpgKeyPair() { + // Create http client + client, err := httpclient.ClientBuilder().Build() + coreutils.ExitOnErr(err) + + // Check if one already exists + resp, body, _, err := client.SendGet(*tests.JfrogUrl+"artifactory/api/security/keypair/"+gpgKeyPairName, true, artHttpDetails, "") + coreutils.ExitOnErr(err) + if resp.StatusCode == http.StatusOK { + return + } + coreutils.ExitOnErr(errorutils.CheckResponseStatusWithBody(resp, body, http.StatusNotFound)) + + // Read gpg public and private keys + keysDir := filepath.Join(tests.GetTestResourcesPath(), lcTestdataPath, "keys") + publicKey, err := os.ReadFile(filepath.Join(keysDir, "public.txt")) + coreutils.ExitOnErr(err) + privateKey, err := os.ReadFile(filepath.Join(keysDir, "private.txt")) + coreutils.ExitOnErr(err) + + // Send keys to Artifactory + payload := KeyPairPayload{ + PairName: gpgKeyPairName, + PairType: "GPG", + Alias: gpgKeyPairName + "-alias", + Passphrase: "password", + PublicKey: string(publicKey), + PrivateKey: string(privateKey), + } + content, err := json.Marshal(payload) + coreutils.ExitOnErr(err) + resp, body, err = client.SendPost(*tests.JfrogUrl+"artifactory/api/security/keypair", content, artHttpDetails, "") + coreutils.ExitOnErr(err) + coreutils.ExitOnErr(errorutils.CheckResponseStatusWithBody(resp, body, http.StatusCreated)) +} + +type KeyPairPayload struct { + PairName string `json:"pairName,omitempty"` + PairType string `json:"pairType,omitempty"` + Alias string `json:"alias,omitempty"` + Passphrase string `json:"passphrase,omitempty"` + PublicKey string `json:"publicKey,omitempty"` + PrivateKey string `json:"privateKey,omitempty"` +} diff --git a/main.go b/main.go index d7d904495..42c3c804c 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "github.com/jfrog/jfrog-cli/lifecycle" "golang.org/x/exp/slices" "os" "runtime" @@ -269,6 +270,7 @@ func getCommands() []cli.Command { allCommands := append(slices.Clone(cliNameSpaces), utils.GetPlugins()...) allCommands = append(allCommands, scan.GetCommands()...) allCommands = append(allCommands, buildtools.GetCommands()...) + allCommands = append(allCommands, lifecycle.GetCommands()...) return append(allCommands, buildtools.GetBuildToolsHelpCommands()...) } diff --git a/main_test.go b/main_test.go index 7bab29827..bc6684073 100644 --- a/main_test.go +++ b/main_test.go @@ -4,34 +4,30 @@ import ( "errors" "flag" "fmt" - "os" - "path/filepath" - "strconv" - "strings" - "testing" - - "github.com/jfrog/jfrog-cli-core/v2/common/spec" - "github.com/jfrog/jfrog-cli-core/v2/utils/config" - coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" - xrayutils "github.com/jfrog/jfrog-cli-core/v2/xray/utils" - "github.com/urfave/cli" - buildinfo "github.com/jfrog/build-info-go/entities" - clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" - + commandUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" + artifactoryUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" + "github.com/jfrog/jfrog-cli-core/v2/common/spec" + "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" "github.com/jfrog/jfrog-cli-core/v2/utils/log" - clientlog "github.com/jfrog/jfrog-client-go/utils/log" - - commandUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" - artifactoryUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" + xrayutils "github.com/jfrog/jfrog-cli-core/v2/xray/utils" "github.com/jfrog/jfrog-cli/artifactory" "github.com/jfrog/jfrog-cli/inttestutils" "github.com/jfrog/jfrog-cli/utils/tests" "github.com/jfrog/jfrog-client-go/utils" + clientlog "github.com/jfrog/jfrog-client-go/utils/log" + clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" "github.com/stretchr/testify/assert" + "github.com/urfave/cli" "gopkg.in/yaml.v2" + "os" + "path/filepath" + "strconv" + "strings" + "testing" ) func TestMain(m *testing.M) { @@ -80,6 +76,9 @@ func setupIntegrationTests() { if *tests.TestTransfer { InitTransferTests() } + if *tests.TestLifecycle { + InitLifecycleTests() + } } func tearDownIntegrationTests() { @@ -98,6 +97,9 @@ func tearDownIntegrationTests() { if *tests.TestTransfer { CleanTransferTests() } + if *tests.TestLifecycle { + CleanLifecycleTests() + } } func InitBuildToolsTests() { @@ -180,7 +182,8 @@ func initArtifactoryCli() { } *tests.JfrogUrl = utils.AddTrailingSlashIfNeeded(*tests.JfrogUrl) artifactoryCli = tests.NewJfrogCli(execMain, "jfrog rt", authenticate(false)) - if (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestPlugins || *tests.TestArtifactoryProject || *tests.TestAccess || *tests.TestTransfer { + if (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestPlugins || *tests.TestArtifactoryProject || + *tests.TestAccess || *tests.TestTransfer || *tests.TestLifecycle { configCli = createConfigJfrogCLI(authenticate(true)) platformCli = tests.NewJfrogCli(execMain, "jfrog", authenticate(false)) } @@ -331,6 +334,12 @@ func initDeploymentViewTest(t *testing.T) (assertDeploymentViewFunc func(), clea return } +func deleteFilesFromRepo(t *testing.T, repoName string) { + deleteSpec := spec.NewBuilder().Pattern(repoName).BuildSpec() + _, _, err := tests.DeleteFiles(deleteSpec, serverDetails) + assert.NoError(t, err) +} + func TestIntro(t *testing.T) { buffer, _, previousLog := coreTests.RedirectLogOutputToBuffer() defer clientlog.SetLogger(previousLog) diff --git a/maven_test.go b/maven_test.go index a41cfc498..e7de3a582 100644 --- a/maven_test.go +++ b/maven_test.go @@ -2,29 +2,25 @@ package main import ( "fmt" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/jfrog/jfrog-cli/inttestutils" - "github.com/jfrog/jfrog-cli/utils/tests/proxy/server/certificate" - "github.com/jfrog/jfrog-client-go/utils/log" - clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" - buildinfo "github.com/jfrog/build-info-go/entities" - "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/mvn" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/common/commands" "github.com/jfrog/jfrog-cli-core/v2/common/spec" - "github.com/jfrog/jfrog-client-go/utils/io/fileutils" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" coreTests "github.com/jfrog/jfrog-cli-core/v2/utils/tests" + "github.com/jfrog/jfrog-cli/inttestutils" "github.com/jfrog/jfrog-cli/utils/tests" cliproxy "github.com/jfrog/jfrog-cli/utils/tests/proxy/server" + "github.com/jfrog/jfrog-cli/utils/tests/proxy/server/certificate" + "github.com/jfrog/jfrog-client-go/utils/io/fileutils" + "github.com/jfrog/jfrog-client-go/utils/log" + clientTestUtils "github.com/jfrog/jfrog-client-go/utils/tests" "github.com/stretchr/testify/assert" + "os" + "path/filepath" + "strings" + "testing" ) const mavenTestsProxyPort = "1028" @@ -34,12 +30,8 @@ var localRepoDir string func cleanMavenTest(t *testing.T) { clientTestUtils.UnSetEnvAndAssert(t, coreutils.HomeDir) - deleteSpec := spec.NewBuilder().Pattern(tests.MvnRepo1).BuildSpec() - _, _, err := tests.DeleteFiles(deleteSpec, serverDetails) - assert.NoError(t, err) - deleteSpec = spec.NewBuilder().Pattern(tests.MvnRepo2).BuildSpec() - _, _, err = tests.DeleteFiles(deleteSpec, serverDetails) - assert.NoError(t, err) + deleteFilesFromRepo(t, tests.MvnRepo1) + deleteFilesFromRepo(t, tests.MvnRepo2) tests.CleanFileSystem() } diff --git a/testdata/dev_repo_repository_config.json b/testdata/dev_repo_repository_config.json new file mode 100644 index 000000000..de2297cfd --- /dev/null +++ b/testdata/dev_repo_repository_config.json @@ -0,0 +1,6 @@ +{ + "key": "${DEV_REPO}", + "rclass": "local", + "packageType": "generic", + "environments":["DEV"] +} diff --git a/testdata/filespecs/search_all_prod_repo.json b/testdata/filespecs/search_all_prod_repo.json new file mode 100644 index 000000000..2930acf50 --- /dev/null +++ b/testdata/filespecs/search_all_prod_repo.json @@ -0,0 +1,7 @@ +{ + "files": [ + { + "pattern": "${PROD_REPO}/*" + } + ] +} \ No newline at end of file diff --git a/testdata/filespecs/upload_dev_spec_a.json b/testdata/filespecs/upload_dev_spec_a.json new file mode 100644 index 000000000..d816a4499 --- /dev/null +++ b/testdata/filespecs/upload_dev_spec_a.json @@ -0,0 +1,10 @@ +{ + "files": [ + { + "pattern": "testdata/a/*", + "target": "${DEV_REPO}/", + "flat": "true", + "recursive": "false" + } + ] +} \ No newline at end of file diff --git a/testdata/filespecs/upload_dev_spec_b.json b/testdata/filespecs/upload_dev_spec_b.json new file mode 100644 index 000000000..e5419e101 --- /dev/null +++ b/testdata/filespecs/upload_dev_spec_b.json @@ -0,0 +1,10 @@ +{ + "files": [ + { + "pattern": "testdata/a/b/*", + "target": "${DEV_REPO}/", + "flat": "true", + "recursive": "false" + } + ] +} \ No newline at end of file diff --git a/testdata/filespecs/upload_dev_spec_c.json b/testdata/filespecs/upload_dev_spec_c.json new file mode 100644 index 000000000..db8e8177f --- /dev/null +++ b/testdata/filespecs/upload_dev_spec_c.json @@ -0,0 +1,10 @@ +{ + "files": [ + { + "pattern": "testdata/a/b/c/*", + "target": "${DEV_REPO}/", + "flat": "true", + "recursive": "false" + } + ] +} \ No newline at end of file diff --git a/testdata/lifecycle/builds-spec-1-2.json b/testdata/lifecycle/builds-spec-1-2.json new file mode 100644 index 000000000..1d31239ca --- /dev/null +++ b/testdata/lifecycle/builds-spec-1-2.json @@ -0,0 +1,13 @@ +{ + "builds": [ + { + "name": "${LC_BUILD_NAME1}", + "number": "111" + }, + { + "name": "${LC_BUILD_NAME2}", + "number": "", + "project": "default" + } + ] +} diff --git a/testdata/lifecycle/builds-spec-3.json b/testdata/lifecycle/builds-spec-3.json new file mode 100644 index 000000000..b188d7eb6 --- /dev/null +++ b/testdata/lifecycle/builds-spec-3.json @@ -0,0 +1,8 @@ +{ + "builds": [ + { + "name": "${LC_BUILD_NAME3}", + "number": "" + } + ] +} diff --git a/testdata/lifecycle/keys/private.txt b/testdata/lifecycle/keys/private.txt new file mode 100644 index 000000000..302ccf64a --- /dev/null +++ b/testdata/lifecycle/keys/private.txt @@ -0,0 +1,83 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +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 +=lBLn +-----END PGP PRIVATE KEY BLOCK----- diff --git a/testdata/lifecycle/keys/public.txt b/testdata/lifecycle/keys/public.txt new file mode 100644 index 000000000..00e214e35 --- /dev/null +++ b/testdata/lifecycle/keys/public.txt @@ -0,0 +1,41 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +m0maxaPoW55LRqmm +=S8pT +-----END PGP PUBLIC KEY BLOCK----- diff --git a/testdata/lifecycle/release-bundles-spec.json b/testdata/lifecycle/release-bundles-spec.json new file mode 100644 index 000000000..36fac6eea --- /dev/null +++ b/testdata/lifecycle/release-bundles-spec.json @@ -0,0 +1,12 @@ +{ + "releaseBundles": [ + { + "name": "${RB_NAME1}", + "version": "111" + }, + { + "name": "${RB_NAME2}", + "version": "222" + } + ] +} diff --git a/testdata/prod_repo_repository_config.json b/testdata/prod_repo_repository_config.json new file mode 100644 index 000000000..6187c443e --- /dev/null +++ b/testdata/prod_repo_repository_config.json @@ -0,0 +1,6 @@ +{ + "key": "${PROD_REPO}", + "rclass": "local", + "packageType": "generic", + "environments":["PROD"] +} diff --git a/utils/cliutils/commandsflags.go b/utils/cliutils/commandsflags.go index 68d9a2a7e..080fea61f 100644 --- a/utils/cliutils/commandsflags.go +++ b/utils/cliutils/commandsflags.go @@ -88,11 +88,11 @@ const ( passphrase = "passphrase" // Distribution's Command Keys - ReleaseBundleCreate = "release-bundle-create" - ReleaseBundleUpdate = "release-bundle-update" - ReleaseBundleSign = "release-bundle-sign" - ReleaseBundleDistribute = "release-bundle-distribute" - ReleaseBundleDelete = "release-bundle-delete" + ReleaseBundleV1Create = "release-bundle-v1-create" + ReleaseBundleV1Update = "release-bundle-v1-update" + ReleaseBundleV1Sign = "release-bundle-v1-sign" + ReleaseBundleV1Distribute = "release-bundle-v1-distribute" + ReleaseBundleV1Delete = "release-bundle-v1-delete" // MC's Commands Keys McConfig = "mc-config" @@ -130,6 +130,10 @@ const ( // TransferInstall commands keys TransferInstall = "transfer-plugin-install" + // Lifecycle commands keys + ReleaseBundleCreate = "release-bundle-create" + ReleaseBundlePromote = "release-bundle-promote" + // *** Artifactory Commands' flags *** // Base flags url = "url" @@ -299,11 +303,11 @@ const ( copyFlag = "copy" failFast = "fail-fast" - async = "async" + Async = "async" // Unique build-discard flags buildDiscardPrefix = "bdi-" - bdiAsync = buildDiscardPrefix + async + bdiAsync = buildDiscardPrefix + Async maxDays = "max-days" maxBuilds = "max-builds" excludeBuilds = "exclude-builds" @@ -405,25 +409,25 @@ const ( // Base flags distUrl = "dist-url" - // Unique release-bundle-* flags - releaseBundlePrefix = "rb-" - rbDryRun = releaseBundlePrefix + dryRun - rbRepo = releaseBundlePrefix + repo - rbPassphrase = releaseBundlePrefix + passphrase - distTarget = releaseBundlePrefix + target - rbDetailedSummary = releaseBundlePrefix + detailedSummary - sign = "sign" - desc = "desc" - releaseNotesPath = "release-notes-path" - releaseNotesSyntax = "release-notes-syntax" - distRules = "dist-rules" - site = "site" - city = "city" - countryCodes = "country-codes" - sync = "sync" - maxWaitMinutes = "max-wait-minutes" - deleteFromDist = "delete-from-dist" - createRepo = "create-repo" + // Unique release-bundle-* v1 flags + releaseBundleV1Prefix = "rbv1-" + rbDryRun = releaseBundleV1Prefix + dryRun + rbRepo = releaseBundleV1Prefix + repo + rbPassphrase = releaseBundleV1Prefix + passphrase + distTarget = releaseBundleV1Prefix + target + rbDetailedSummary = releaseBundleV1Prefix + detailedSummary + sign = "sign" + desc = "desc" + releaseNotesPath = "release-notes-path" + releaseNotesSyntax = "release-notes-syntax" + distRules = "dist-rules" + site = "site" + city = "city" + countryCodes = "country-codes" + sync = "sync" + maxWaitMinutes = "max-wait-minutes" + deleteFromDist = "delete-from-dist" + createRepo = "create-repo" // *** Xray Commands' flags *** // Base flags @@ -532,6 +536,19 @@ const ( installPluginVersion = installPluginPrefix + Version InstallPluginSrcDir = "dir" InstallPluginHomeDir = "home-dir" + + // Unique lifecycle flags + lifecyclePrefix = "lc-" + lcUrl = lifecyclePrefix + url + lcSync = lifecyclePrefix + Sync + lcProject = lifecyclePrefix + project + Builds = "builds" + lcBuilds = lifecyclePrefix + Builds + ReleaseBundles = "release-bundles" + lcReleaseBundles = lifecyclePrefix + ReleaseBundles + SigningKey = "signing-key" + lcSigningKey = lifecyclePrefix + SigningKey + lcOverwrite = lifecyclePrefix + Overwrite ) var flagsMap = map[string]cli.Flag{ @@ -987,7 +1004,7 @@ var flagsMap = map[string]cli.Flag{ Usage: "[Default: false] If set to true, automatically removes build artifacts stored in Artifactory.` `", }, bdiAsync: cli.BoolFlag{ - Name: async, + Name: Async, Usage: "[Default: false] If set to true, build discard will run asynchronously and will not wait for response.` `", }, refs: cli.StringFlag{ @@ -1348,7 +1365,7 @@ var flagsMap = map[string]cli.Flag{ }, xrOutput: cli.StringFlag{ Name: xrOutput, - Usage: "[Default: table] Defines the output format of the command. Acceptable values are: table, json, simple-json and sarif. Note: the json format doesn’t include information about scans that are included as part of the Advanced Security package.` `", + Usage: "[Default: table] Defines the output format of the command. Acceptable values are: table, json, simple-json and sarif. Note: the json format doesn't include information about scans that are included as part of the Advanced Security package.` `", }, BypassArchiveLimits: cli.BoolFlag{ Name: BypassArchiveLimits, @@ -1556,6 +1573,34 @@ var flagsMap = map[string]cli.Flag{ Name: PreChecks, Usage: "[Default: false] Set to true to run pre transfer checks.` `", }, + lcUrl: cli.StringFlag{ + Name: url, + Usage: "[Optional] JFrog platform URL.` `", + }, + lcSync: cli.BoolFlag{ + Name: Sync, + Usage: "[Default: false] Set to true to run synchronously.` `", + }, + lcProject: cli.StringFlag{ + Name: project, + Usage: "[Optional] Project key associated with the Release Bundle version.` `", + }, + lcBuilds: cli.StringFlag{ + Name: Builds, + Usage: "[Optional] Path to a JSON file containing information of the source builds from which to create a release bundle.` `", + }, + lcReleaseBundles: cli.StringFlag{ + Name: ReleaseBundles, + Usage: "[Optional] Path to a JSON file containing information of the source release bundles from which to create a release bundle.` `", + }, + lcSigningKey: cli.StringFlag{ + Name: SigningKey, + Usage: "[Mandatory] The GPG/RSA key-pair name given in Artifactory.` `", + }, + lcOverwrite: cli.BoolFlag{ + Name: Overwrite, + Usage: "[Default: false] Set to true to replace artifacts with the same name but a different checksum if such already exist at the promotion targets. By default, the promotion is stopped in a case of such conflict.` `", + }, } var commandFlags = map[string][]string{ @@ -1766,23 +1811,23 @@ var commandFlags = map[string][]string{ Poetry: { buildName, buildNumber, module, project, }, - ReleaseBundleCreate: { + ReleaseBundleV1Create: { distUrl, user, password, accessToken, serverId, specFlag, specVars, targetProps, rbDryRun, sign, desc, exclusions, releaseNotesPath, releaseNotesSyntax, rbPassphrase, rbRepo, InsecureTls, distTarget, rbDetailedSummary, }, - ReleaseBundleUpdate: { + ReleaseBundleV1Update: { distUrl, user, password, accessToken, serverId, specFlag, specVars, targetProps, rbDryRun, sign, desc, exclusions, releaseNotesPath, releaseNotesSyntax, rbPassphrase, rbRepo, InsecureTls, distTarget, rbDetailedSummary, }, - ReleaseBundleSign: { + ReleaseBundleV1Sign: { distUrl, user, password, accessToken, serverId, rbPassphrase, rbRepo, InsecureTls, rbDetailedSummary, }, - ReleaseBundleDistribute: { + ReleaseBundleV1Distribute: { distUrl, user, password, accessToken, serverId, rbDryRun, distRules, site, city, countryCodes, sync, maxWaitMinutes, InsecureTls, createRepo, }, - ReleaseBundleDelete: { + ReleaseBundleV1Delete: { distUrl, user, password, accessToken, serverId, rbDryRun, distRules, site, city, countryCodes, sync, maxWaitMinutes, InsecureTls, deleteFromDist, deleteQuiet, }, @@ -1834,6 +1879,12 @@ var commandFlags = map[string][]string{ TransferInstall: { installPluginVersion, InstallPluginSrcDir, InstallPluginHomeDir, }, + ReleaseBundleCreate: { + lcUrl, user, password, accessToken, serverId, lcSigningKey, lcSync, lcProject, lcBuilds, lcReleaseBundles, + }, + ReleaseBundlePromote: { + lcUrl, user, password, accessToken, serverId, lcSigningKey, lcSync, lcProject, lcOverwrite, + }, // Xray's commands OfflineUpdate: { licenseId, from, to, Version, target, Stream, Periodic, diff --git a/utils/cliutils/utils.go b/utils/cliutils/utils.go index 887af601b..ffcfe7558 100644 --- a/utils/cliutils/utils.go +++ b/utils/cliutils/utils.go @@ -33,9 +33,10 @@ import ( type CommandDomain string const ( - Rt CommandDomain = "rt" - Ds CommandDomain = "ds" - Xr CommandDomain = "xr" + Rt CommandDomain = "rt" + Ds CommandDomain = "ds" + Xr CommandDomain = "xr" + Platform CommandDomain = "platform" ) // Error modes (how should the application behave when the CheckError function is invoked): @@ -530,6 +531,8 @@ func createServerDetailsFromFlags(c *cli.Context, domain CommandDomain) (details details.XrayUrl = details.Url case Ds: details.DistributionUrl = details.Url + case Platform: + return } details.Url = "" @@ -853,3 +856,12 @@ func doHttpRequest(client *http.Client, req *http.Request) (resp *http.Response, body, err = io.ReadAll(resp.Body) return resp, body, errorutils.CheckError(err) } + +// Get project key from flag or environment variable +func GetProject(c *cli.Context) string { + projectKey := c.String("project") + if projectKey == "" { + projectKey = os.Getenv(coreutils.Project) + } + return projectKey +} diff --git a/utils/tests/consts.go b/utils/tests/consts.go index 23c5202c9..a4c52191c 100644 --- a/utils/tests/consts.go +++ b/utils/tests/consts.go @@ -1,13 +1,11 @@ package tests import ( - "path/filepath" - - "github.com/jfrog/jfrog-client-go/artifactory/services" - "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" - servicesutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" - clientutils "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-client-go/artifactory/services" + servicesUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" + clientUtils "github.com/jfrog/jfrog-client-go/utils" + "path/filepath" ) const ( @@ -93,6 +91,7 @@ const ( SearchAllMaven = "search_all_maven.json" SearchAllNpm = "search_all_npm.json" SearchAllRepo1 = "search_all_repo1.json" + SearchAllProdRepo = "search_all_prod_repo.json" SearchDistRepoByInSuffix = "search_dist_repo_by_in_suffix.json" SearchRepo1ByInSuffix = "search_repo1_by_in_suffix.json" SearchRepo1IncludeDirs = "search_repo1_include_dirs.json" @@ -148,6 +147,11 @@ const ( DockerRemoteRepositoryConfig = "docker_remote_repository_config.json" DockerVirtualRepositoryConfig = "docker_virtual_repository_config.json" XrayEndpoint = "xray/" + DevRepoRepositoryConfig = "dev_repo_repository_config.json" + ProdRepoRepositoryConfig = "prod_repo_repository_config.json" + UploadDevSpecA = "upload_dev_spec_a.json" + UploadDevSpecB = "upload_dev_spec_b.json" + UploadDevSpecC = "upload_dev_spec_c.json" ) var ( @@ -181,6 +185,9 @@ var ( RtRepo1 = "cli-rt1" RtRepo2 = "cli-rt2" RtVirtualRepo = "cli-rt-virtual" + // Repositories that are assigned to an environment. + RtDevRepo = "cli-rt-dev" + RtProdRepo = "cli-rt-prod" // These are not actual repositories. These patterns are meant to be used in both Repo1 and Repo2. RtRepo1And2 = "cli-rt*" RtRepo1And2Placeholder = "cli-rt(*)" @@ -202,6 +209,12 @@ var ( RtBuildName2 = "cli-rt-build2" RtBuildNameWithSpecialChars = "cli-rt-a$+~&^a#-build3" RtPermissionTargetName = "cli-rt-pt" + LcBuildName1 = "cli-lc-build1" + LcBuildName2 = "cli-lc-build2" + LcBuildName3 = "cli-lc-build3" + LcRbName1 = "cli-lc-rb1" + LcRbName2 = "cli-lc-rb2" + LcRbName3 = "cli-lc-rb3" // Users UserName1 = "alice" @@ -249,16 +262,6 @@ func GetExpectedExcludeUploadPart2() []string { RtRepo1 + "/", } } -func GetExpectedExcludeUpload2() []string { - return []string{ - RtRepo1 + "/b3.in", - RtRepo1 + "/a2.in", - RtRepo1 + "/a3.in", - RtRepo1 + "/a1.in", - RtRepo1 + "/c", - RtRepo1 + "/", - } -} func GetExpectedExcludeUploadIncludeDir() []string { return []string{ RtRepo1 + "/a2.in", @@ -269,14 +272,6 @@ func GetExpectedExcludeUploadIncludeDir() []string { } } -func GetUploadLegacyPropsExpected() []string { - return []string{ - RtRepo1 + "/data/a1.in", - RtRepo1 + "/data/a2.in", - RtRepo1 + "/data/a3.in", - } -} - func GetSearchAppendedBuildNoPatternExpected() []string { return []string{ RtRepo1 + "/data/a1.in", @@ -1739,12 +1734,6 @@ func GetSearchResultAfterDeleteByPropsStep3() []utils.SearchResult { } } -func GetDockerSourceManifest() []string { - return []string{ - DockerLocalRepo + "/" + DockerImageName + "/1/manifest.json", - } -} - func GetDockerDeployedManifest() []string { return []string{ DockerLocalPromoteRepo + "/" + DockerImageName + "promotion" + "/2/manifest.json", @@ -1972,17 +1961,17 @@ func GetFileWithDownloadedPlaceHolderSlashSuffix() []string { } } -func GetExpectedUploadSummaryDetails(rtUrl string) []clientutils.FileTransferDetails { +func GetExpectedUploadSummaryDetails(rtUrl string) []clientUtils.FileTransferDetails { path1, path2, path3 := filepath.Join("testdata", "a", "a1.in"), filepath.Join("testdata", "a", "a2.in"), filepath.Join("testdata", "a", "a3.in") - return []clientutils.FileTransferDetails{ + return []clientUtils.FileTransferDetails{ {SourcePath: path1, RtUrl: rtUrl, TargetPath: RtRepo1 + "/testdata/a/a1.in", Sha256: "4eb341b5d2762a853d79cc25e622aa8b978eb6e12c3259e2d99dc9dc60d82c5d"}, {SourcePath: path2, RtUrl: rtUrl, TargetPath: RtRepo1 + "/testdata/a/a2.in", Sha256: "3e3deb6628658a48cf0d280a2210211f9d977ec2e10a4619b95d5fb85cb10450"}, {SourcePath: path3, RtUrl: rtUrl, TargetPath: RtRepo1 + "/testdata/a/a3.in", Sha256: "14e3dc4749bf42df13a67a271065b0f334d0ad36bb34a74cc57c6e137f9af09e"}, } } -func GetReplicationConfig() []servicesutils.ReplicationParams { - return []servicesutils.ReplicationParams{ +func GetReplicationConfig() []servicesUtils.ReplicationParams { + return []servicesUtils.ReplicationParams{ { Url: *JfrogUrl + ArtifactoryEndpoint + "targetRepo", Username: "admin", @@ -2075,3 +2064,17 @@ func GetTransferExpectedRepoSnapshot() []string { RtRepo1 + "/testdata/a/b/b3.in", } } + +func GetExpectedLifecycleArtifacts() []string { + return []string{ + RtProdRepo + "/a1.in", + RtProdRepo + "/a2.in", + RtProdRepo + "/a3.in", + RtProdRepo + "/b1.in", + RtProdRepo + "/b2.in", + RtProdRepo + "/b3.in", + RtProdRepo + "/c1.in", + RtProdRepo + "/c2.in", + RtProdRepo + "/c3.in", + } +} diff --git a/utils/tests/utils.go b/utils/tests/utils.go index 5f245f63e..bfd9d0a6d 100644 --- a/utils/tests/utils.go +++ b/utils/tests/utils.go @@ -7,6 +7,7 @@ import ( "errors" "flag" "fmt" + "github.com/urfave/cli" "io" "math/rand" "os" @@ -68,6 +69,7 @@ var ( TestXray *bool TestAccess *bool TestTransfer *bool + TestLifecycle *bool HideUnitTestLog *bool ciRunId *string InstallDataTransferPlugin *bool @@ -103,6 +105,7 @@ func init() { TestXray = flag.Bool("test.xray", false, "Test Xray") TestAccess = flag.Bool("test.access", false, "Test Access") TestTransfer = flag.Bool("test.transfer", false, "Test files transfer") + TestLifecycle = flag.Bool("test.lc", false, "Test lifecycle") ContainerRegistry = flag.String("test.containerRegistry", "localhost:8082", "Container registry") HideUnitTestLog = flag.Bool("test.hideUnitTestLog", false, "Hide unit tests logs and print it in a file") InstallDataTransferPlugin = flag.Bool("test.installDataTransferPlugin", false, "Install data-transfer plugin on the source Artifactory server") @@ -349,6 +352,8 @@ var reposConfigMap = map[*string]string{ &DockerLocalPromoteRepo: DockerLocalPromoteRepositoryConfig, &DockerRemoteRepo: DockerRemoteRepositoryConfig, &DockerVirtualRepo: DockerVirtualRepositoryConfig, + &RtDevRepo: DevRepoRepositoryConfig, + &RtProdRepo: ProdRepoRepositoryConfig, } var CreatedNonVirtualRepositories map[*string]string @@ -399,6 +404,7 @@ func GetNonVirtualRepositories() map[*string]string { TestXray: {}, TestAccess: {&RtRepo1}, TestTransfer: {&RtRepo1, &RtRepo2, &MvnRepo1, &MvnRemoteRepo, &DockerRemoteRepo}, + TestLifecycle: {&RtDevRepo, &RtProdRepo}, } return getNeededRepositories(nonVirtualReposMap) } @@ -459,6 +465,7 @@ func GetBuildNames() []string { TestXray: {}, TestAccess: {}, TestTransfer: {&MvnBuildName}, + TestLifecycle: {&LcBuildName1, &LcBuildName2, &LcBuildName3}, } return getNeededBuildNames(buildNamesMap) } @@ -512,6 +519,13 @@ func getSubstitutionMap() map[string]string { "{PASSWORD_1}": Password1, "{USER_NAME_2}": UserName2, "{PASSWORD_2}": Password2, + "${LC_BUILD_NAME1}": LcBuildName1, + "${LC_BUILD_NAME2}": LcBuildName2, + "${LC_BUILD_NAME3}": LcBuildName3, + "${RB_NAME1}": LcRbName1, + "${RB_NAME2}": LcRbName2, + "${DEV_REPO}": RtDevRepo, + "${PROD_REPO}": RtProdRepo, } } @@ -561,6 +575,8 @@ func AddTimestampToGlobalVars() { RtRepo1And2Placeholder += uniqueSuffix RtRepo2 += uniqueSuffix RtVirtualRepo += uniqueSuffix + RtDevRepo += uniqueSuffix + RtProdRepo += uniqueSuffix // Builds/bundles/images BundleName += uniqueSuffix @@ -580,6 +596,12 @@ func AddTimestampToGlobalVars() { RtBuildName2 += uniqueSuffix RtBuildNameWithSpecialChars += uniqueSuffix RtPermissionTargetName += uniqueSuffix + LcBuildName1 += uniqueSuffix + LcBuildName2 += uniqueSuffix + LcBuildName3 += uniqueSuffix + LcRbName1 += uniqueSuffix + LcRbName2 += uniqueSuffix + LcRbName3 += uniqueSuffix // Users UserName1 += uniqueSuffix @@ -778,3 +800,24 @@ func SkipKnownFailingTest(t *testing.T) { t.Error("Not skipping test. Please fix the test or delay the skipMonth") } } + +func CreateContext(t *testing.T, testFlags, testArgs []string) (*cli.Context, *bytes.Buffer) { + flagSet := createFlagSet(t, testFlags, testArgs) + app := cli.NewApp() + app.Writer = &bytes.Buffer{} + return cli.NewContext(app, flagSet, nil), &bytes.Buffer{} +} + +// Create flag set with input flags and arguments. +func createFlagSet(t *testing.T, flags []string, args []string) *flag.FlagSet { + flagSet := flag.NewFlagSet("TestFlagSet", flag.ContinueOnError) + flags = append(flags, "url=http://127.0.0.1:8081/artifactory") + var cmdFlags []string + for _, curFlag := range flags { + flagSet.String(strings.Split(curFlag, "=")[0], "", "") + cmdFlags = append(cmdFlags, "--"+curFlag) + } + cmdFlags = append(cmdFlags, args...) + assert.NoError(t, flagSet.Parse(cmdFlags)) + return flagSet +} From ab6ae71d00f2c0dfdc1ba16e2bf77cd50d9225f0 Mon Sep 17 00:00:00 2001 From: Robi Nino Date: Thu, 29 Jun 2023 23:18:23 +0300 Subject: [PATCH 11/25] Promote version to 2.42.0 (#2052) --- build/npm/v2-jf/package-lock.json | 2 +- build/npm/v2-jf/package.json | 2 +- build/npm/v2/package-lock.json | 2 +- build/npm/v2/package.json | 2 +- go.mod | 8 ++++---- go.sum | 8 ++++---- utils/cliutils/cli_consts.go | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index e7fe21f0e..edc8d1731 100644 --- a/build/npm/v2-jf/package-lock.json +++ b/build/npm/v2-jf/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.41.1", + "version": "2.42.0", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index ac8a5f918..b9048b41d 100644 --- a/build/npm/v2-jf/package.json +++ b/build/npm/v2-jf/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.41.1", + "version": "2.42.0", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/npm/v2/package-lock.json b/build/npm/v2/package-lock.json index 439ff2702..09abf5d1c 100644 --- a/build/npm/v2/package-lock.json +++ b/build/npm/v2/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2", - "version": "2.41.1", + "version": "2.42.0", "lockfileVersion": 1 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index 748eec5dd..019177a9b 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.41.1", + "version": "2.42.0", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/go.mod b/go.mod index c516a946e..679653133 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d github.com/jfrog/build-info-go v1.9.6 github.com/jfrog/gofrog v1.3.0 - github.com/jfrog/jfrog-cli-core/v2 v2.36.1 - github.com/jfrog/jfrog-client-go v1.30.1 + github.com/jfrog/jfrog-cli-core/v2 v2.37.0 + github.com/jfrog/jfrog-client-go v1.31.0 github.com/jszwec/csvutil v1.8.0 github.com/mholt/archiver/v3 v3.5.1 github.com/pkg/errors v0.9.1 @@ -123,8 +123,8 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230629184314-ff61ffffba34 +// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230629184314-ff61ffffba34 // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230629174113-81715f46ec0f +// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230629174113-81715f46ec0f diff --git a/go.sum b/go.sum index 6e5785091..284146cf8 100644 --- a/go.sum +++ b/go.sum @@ -238,10 +238,10 @@ github.com/jfrog/build-info-go v1.9.6 h1:lCJ2j5uXAlJsSwDe5J8WD7Co1f/hUlZvMfwfb5A github.com/jfrog/build-info-go v1.9.6/go.mod h1:GbuFS+viHCKZYx9nWHYu7ab1DgQkFdtVN3BJPUNb2D4= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230629184314-ff61ffffba34 h1:i1nENbEtG6uv5V92UacU6okTW3zcH1VfzmkvJn9nK7Y= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230629184314-ff61ffffba34/go.mod h1:zc3la+URXmlEvrDhcY2g4AnnAQPOsmJisVfJZM06o+g= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230629174113-81715f46ec0f h1:FzagM0DDnwhcOCR+/grBwrg625a8mwOdytnJTlGCkAI= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230629174113-81715f46ec0f/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= +github.com/jfrog/jfrog-cli-core/v2 v2.37.0 h1:lKU2+/1Yn5eKRpyxI8cogzWUEh0NBZJqeaJTxghtAa8= +github.com/jfrog/jfrog-cli-core/v2 v2.37.0/go.mod h1:i62WcX9jQbH0dJjQdkmJAGridZgFVIK1B3yIPfXayHI= +github.com/jfrog/jfrog-client-go v1.31.0 h1:VIptdPkECaM0UDbKE2ZjFZh9i85W99xM65c6rFxDNj4= +github.com/jfrog/jfrog-client-go v1.31.0/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index ce9c0b1d2..2ae2dbd68 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -4,7 +4,7 @@ import "time" const ( // General CLI constants - CliVersion = "2.41.1" + CliVersion = "2.42.0" ClientAgent = "jfrog-cli-go" // CLI base commands constants: From 74153b974ed7d88ee771df0f3311d78a0c22f7d5 Mon Sep 17 00:00:00 2001 From: Yahav Itzhak Date: Tue, 4 Jul 2023 12:40:36 +0300 Subject: [PATCH 12/25] Promote to version 2.42.1 (#2058) --- build/npm/v2-jf/package-lock.json | 2 +- build/npm/v2-jf/package.json | 2 +- build/npm/v2/package-lock.json | 2 +- build/npm/v2/package.json | 2 +- go.mod | 2 +- go.sum | 4 ++-- utils/cliutils/cli_consts.go | 2 +- utils/progressbar/readerprogressbar.go | 1 + utils/progressbar/simpleprogressbar.go | 1 + utils/tests/utils.go | 2 +- 10 files changed, 11 insertions(+), 9 deletions(-) diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index edc8d1731..6a02eeb2a 100644 --- a/build/npm/v2-jf/package-lock.json +++ b/build/npm/v2-jf/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.42.0", + "version": "2.42.1", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index b9048b41d..eaef6b839 100644 --- a/build/npm/v2-jf/package.json +++ b/build/npm/v2-jf/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.42.0", + "version": "2.42.1", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/npm/v2/package-lock.json b/build/npm/v2/package-lock.json index 09abf5d1c..47f24e3de 100644 --- a/build/npm/v2/package-lock.json +++ b/build/npm/v2/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2", - "version": "2.42.0", + "version": "2.42.1", "lockfileVersion": 1 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index 019177a9b..0c66a040e 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.42.0", + "version": "2.42.1", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/go.mod b/go.mod index 679653133..c67223b40 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d github.com/jfrog/build-info-go v1.9.6 github.com/jfrog/gofrog v1.3.0 - github.com/jfrog/jfrog-cli-core/v2 v2.37.0 + github.com/jfrog/jfrog-cli-core/v2 v2.37.1 github.com/jfrog/jfrog-client-go v1.31.0 github.com/jszwec/csvutil v1.8.0 github.com/mholt/archiver/v3 v3.5.1 diff --git a/go.sum b/go.sum index 284146cf8..f53e8dd10 100644 --- a/go.sum +++ b/go.sum @@ -238,8 +238,8 @@ github.com/jfrog/build-info-go v1.9.6 h1:lCJ2j5uXAlJsSwDe5J8WD7Co1f/hUlZvMfwfb5A github.com/jfrog/build-info-go v1.9.6/go.mod h1:GbuFS+viHCKZYx9nWHYu7ab1DgQkFdtVN3BJPUNb2D4= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.37.0 h1:lKU2+/1Yn5eKRpyxI8cogzWUEh0NBZJqeaJTxghtAa8= -github.com/jfrog/jfrog-cli-core/v2 v2.37.0/go.mod h1:i62WcX9jQbH0dJjQdkmJAGridZgFVIK1B3yIPfXayHI= +github.com/jfrog/jfrog-cli-core/v2 v2.37.1 h1:VE/6cagGor/5lWB7l+aU5FlhztoHM9q9M2FlWcn3ESo= +github.com/jfrog/jfrog-cli-core/v2 v2.37.1/go.mod h1:i62WcX9jQbH0dJjQdkmJAGridZgFVIK1B3yIPfXayHI= github.com/jfrog/jfrog-client-go v1.31.0 h1:VIptdPkECaM0UDbKE2ZjFZh9i85W99xM65c6rFxDNj4= github.com/jfrog/jfrog-client-go v1.31.0/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index 2ae2dbd68..9ce4b4c2c 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -4,7 +4,7 @@ import "time" const ( // General CLI constants - CliVersion = "2.42.0" + CliVersion = "2.42.1" ClientAgent = "jfrog-cli-go" // CLI base commands constants: diff --git a/utils/progressbar/readerprogressbar.go b/utils/progressbar/readerprogressbar.go index 19f396794..0ccef8190 100644 --- a/utils/progressbar/readerprogressbar.go +++ b/utils/progressbar/readerprogressbar.go @@ -27,6 +27,7 @@ func (p *ReaderProgressBar) Abort() { } // GetId Returns the ProgressBar ID +// //nolint:gocritic func (p *ReaderProgressBar) GetId() (Id int) { return p.Id diff --git a/utils/progressbar/simpleprogressbar.go b/utils/progressbar/simpleprogressbar.go index 85e816306..a6695acf3 100644 --- a/utils/progressbar/simpleprogressbar.go +++ b/utils/progressbar/simpleprogressbar.go @@ -21,6 +21,7 @@ func (p *SimpleProgressBar) Abort() { } // GetId Returns the ProgressBar ID +// //nolint:gocritic func (p *SimpleProgressBar) GetId() (Id int) { return p.Id diff --git a/utils/tests/utils.go b/utils/tests/utils.go index bfd9d0a6d..227f96b43 100644 --- a/utils/tests/utils.go +++ b/utils/tests/utils.go @@ -793,7 +793,7 @@ func VerifySha256DetailedSummaryFromResult(t *testing.T, result *commandutils.Re } func SkipKnownFailingTest(t *testing.T) { - skipDate := time.Date(2023, time.July, 0, 0, 0, 0, 0, time.UTC) + skipDate := time.Date(2023, time.August, 0, 0, 0, 0, 0, time.UTC) if time.Now().Before(skipDate) { t.Skip("Skipping a known failing test, will resume testing after ", skipDate.String()) } else { From 9e3efbe451ec0a801f7bbf704ea0e7d71cda928a Mon Sep 17 00:00:00 2001 From: Yahav Itzhak Date: Tue, 4 Jul 2023 14:20:24 +0300 Subject: [PATCH 13/25] Avoid creating the release on GitHub (#2059) --- Jenkinsfile | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index ec5c772ef..16c3d1d27 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -133,7 +133,7 @@ def runRelease(architectures) { } } if (identifier == "v2") { - createTagAndRelease() + createTag() } } } finally { @@ -141,7 +141,7 @@ def runRelease(architectures) { } } -def createTagAndRelease() { +def createTag() { stage('Create a tag and a GitHub release') { dir("$jfrogCliRepoDir") { releaseTag = "v$RELEASE_VERSION" @@ -149,13 +149,6 @@ def createTagAndRelease() { sh """#!/bin/bash git tag $releaseTag git push "https://$GITHUB_ACCESS_TOKEN@github.com/jfrog/jfrog-cli.git" --tags - curl -L \ - -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GITHUB_ACCESS_TOKEN"\ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/repos/jfrog/jfrog-cli/releases \ - -d '{"tag_name":"$releaseTag","target_commitish":"$BRANCH","name":"$RELEASE_VERSION","generate_release_notes":true}' """ } } From 9bcf74e5319eca4030944ef23748db53c99eba04 Mon Sep 17 00:00:00 2001 From: Robi Nino Date: Wed, 5 Jul 2023 11:49:30 +0300 Subject: [PATCH 14/25] Add support for Web Login (#2036) --- docs/general/login/help.go | 7 +++++++ general/login/cli.go | 14 ++++++++++++++ go.mod | 4 ++-- go.sum | 8 ++++---- main.go | 11 +++++++++++ 5 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 docs/general/login/help.go create mode 100644 general/login/cli.go diff --git a/docs/general/login/help.go b/docs/general/login/help.go new file mode 100644 index 000000000..2b5a82c06 --- /dev/null +++ b/docs/general/login/help.go @@ -0,0 +1,7 @@ +package login + +var Usage = []string{"login"} + +func GetDescription() string { + return "Log in to a JFrog Platform via your web browser. Available for Artifactory 7.63.1 and above" +} diff --git a/general/login/cli.go b/general/login/cli.go new file mode 100644 index 000000000..437142240 --- /dev/null +++ b/general/login/cli.go @@ -0,0 +1,14 @@ +package login + +import ( + coreLogin "github.com/jfrog/jfrog-cli-core/v2/general/login" + "github.com/jfrog/jfrog-cli/utils/cliutils" + "github.com/urfave/cli" +) + +func LoginCmd(c *cli.Context) error { + if c.NArg() > 0 { + return cliutils.WrongNumberOfArgumentsHandler(c) + } + return coreLogin.NewLoginCommand().Run() +} diff --git a/go.mod b/go.mod index c67223b40..92e1934e0 100644 --- a/go.mod +++ b/go.mod @@ -123,8 +123,8 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230629184314-ff61ffffba34 +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230705084348-c7d33487e393 // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230629174113-81715f46ec0f +replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228 diff --git a/go.sum b/go.sum index f53e8dd10..789c83244 100644 --- a/go.sum +++ b/go.sum @@ -238,10 +238,10 @@ github.com/jfrog/build-info-go v1.9.6 h1:lCJ2j5uXAlJsSwDe5J8WD7Co1f/hUlZvMfwfb5A github.com/jfrog/build-info-go v1.9.6/go.mod h1:GbuFS+viHCKZYx9nWHYu7ab1DgQkFdtVN3BJPUNb2D4= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.37.1 h1:VE/6cagGor/5lWB7l+aU5FlhztoHM9q9M2FlWcn3ESo= -github.com/jfrog/jfrog-cli-core/v2 v2.37.1/go.mod h1:i62WcX9jQbH0dJjQdkmJAGridZgFVIK1B3yIPfXayHI= -github.com/jfrog/jfrog-client-go v1.31.0 h1:VIptdPkECaM0UDbKE2ZjFZh9i85W99xM65c6rFxDNj4= -github.com/jfrog/jfrog-client-go v1.31.0/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230705084348-c7d33487e393 h1:zIaBtAjalQ7HLwiYcR3OSU9Jglpmhtw8rg6piYervNU= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230705084348-c7d33487e393/go.mod h1:DnamqHWhKmrmWlCRG3i3z8Wn0JRtNFMC+Bu8TCFzSPY= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228 h1:bkOkjb6sVqo6Jgw9eYSH58jIFPOJvFvwt+jIXvef7QM= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/main.go b/main.go index 42c3c804c..7f8dcd7b8 100644 --- a/main.go +++ b/main.go @@ -22,8 +22,10 @@ import ( "github.com/jfrog/jfrog-cli/distribution" "github.com/jfrog/jfrog-cli/docs/common" "github.com/jfrog/jfrog-cli/docs/general/cisetup" + loginDocs "github.com/jfrog/jfrog-cli/docs/general/login" cisetupcommand "github.com/jfrog/jfrog-cli/general/cisetup" "github.com/jfrog/jfrog-cli/general/envsetup" + "github.com/jfrog/jfrog-cli/general/login" "github.com/jfrog/jfrog-cli/general/project" "github.com/jfrog/jfrog-cli/missioncontrol" "github.com/jfrog/jfrog-cli/pipelines" @@ -266,6 +268,15 @@ func getCommands() []cli.Command { fmt.Println(common.GetGlobalEnvVars()) }, }, + { + Name: "login", + Usage: loginDocs.GetDescription(), + HelpName: corecommon.CreateUsage("login", loginDocs.GetDescription(), loginDocs.Usage), + BashComplete: corecommon.CreateBashCompletionFunc(), + Category: otherCategory, + Action: login.LoginCmd, + Hidden: true, // TODO remove when Artifactory 7.63.1 is released to self-hosted + }, } allCommands := append(slices.Clone(cliNameSpaces), utils.GetPlugins()...) allCommands = append(allCommands, scan.GetCommands()...) From c8a87b5ca4da73a1ac448f51814e00ee4d03cfc5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 08:54:26 +0300 Subject: [PATCH 15/25] Upgrade google.golang.org/grpc to 1.53.0 (#2062) --- go.mod | 4 ++-- go.sum | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 92e1934e0..54ef69c82 100644 --- a/go.mod +++ b/go.mod @@ -113,8 +113,8 @@ require ( golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.9.0 // indirect golang.org/x/text v0.9.0 // indirect - google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect - google.golang.org/grpc v1.52.0 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + google.golang.org/grpc v1.53.0 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index 789c83244..4f993c508 100644 --- a/go.sum +++ b/go.sum @@ -222,6 +222,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.5.3 h1:twfIhZs4QLCtimkP7MOxlF3A0U/5cDPseRT9M/+2SCE= github.com/gookit/color v1.5.3/go.mod h1:NUzwzeehUfl7GIb36pqId+UGmRfQcU/WiiyTTeNjHtE= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -743,6 +744,8 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY= google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -761,6 +764,8 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From d1d70fef3268aa35e929748b29386998760c9acf Mon Sep 17 00:00:00 2001 From: Asaf Ambar Date: Wed, 12 Jul 2023 07:15:05 +0300 Subject: [PATCH 16/25] Curation command documentation. (#2066) --- documentation/CLI-for-JFrog-Curation.md | 68 ++++++++++++++++++++++++ documentation/cli.ftmap | 2 + documentation/images/jf-ca-output.png | Bin 0 -> 102737 bytes 3 files changed, 70 insertions(+) create mode 100644 documentation/CLI-for-JFrog-Curation.md create mode 100644 documentation/images/jf-ca-output.png diff --git a/documentation/CLI-for-JFrog-Curation.md b/documentation/CLI-for-JFrog-Curation.md new file mode 100644 index 000000000..d09a0113a --- /dev/null +++ b/documentation/CLI-for-JFrog-Curation.md @@ -0,0 +1,68 @@ +JFrog CLI : CLI for JFrog Curation +====================================== + + +Overview +-------- +JFrog Curation enables you to block malicious or risky open-source packages entering your software supply chain, preventing consumption in any software pipeline. +What can you do with Curation? +* Track the open-source packages downloaded by your organization to gain centralized visibility and control. +* Prevent harmful packages from getting into your software development pipelines. +* Protect against known and unknown threats, allowing only trusted software packages into your SDLC. +* Create policies to block packages with known vulnerabilities, malicious code, operational risk, or license compliance issues. + +For more information on JFrog Curation and how to set it up, see the JFrog Curation general documentation. + +JFrog Curation requires [Xray version 3.78.9](https://jfrog.com/help/r/jfrog-release-information/xray-3.78.9) and above, and [Artifactory version 7.63.2](https://jfrog.com/help/r/jfrog-release-information/artifactory-7.63.2-cloud) and above. It also requires Enterprise X and Enterprise + subscriptions. + +--- + +### Commands + +Audit your Project with JFrog Curation + + +**Note** +> The **curation-audit** command currently only supports npm projects. + +The **jf curation-audit** command enables developers to scan project dependencies to find packages that were blocked by the JFrog curation service. This command provides developers with more detailed information, such as whether the blocked package is the project’s direct dependency or is a transitive dependency. This information helps developers to resolve blocked packages more efficiently as they will be able to make a more informative decision based on what Policy violation occurred and what exactly needs to be resolved. + +For each blocked package the CLI provides the violated Curation Policies. The command builds a deep dependencies graph for the project, and requests the Curation status by a HEAD request for each node in the tree. It uses the package manager that is used in the project to build the dependencies graph. + +Before running the command, do the following: +1) Connect the JFrog CLI to your JFrog Platform instance by running the **jf c add** command. +2) Ensure your project is configured in the JFrog CLI with the repository you would like to resolve dependencies from. Set the repository with the **jf npmc** command inside the project directory. +

+ + +| | | +|-----------------------|-----------------------------------------------------------------------------------------------------------------------------------| +| **Command name** | curation-audit | +| **Abbreviation** | ca | +| **Command options** | | +| --format | \[Default: table\]

Defines the output format of the command. Acceptable values are: table and json. | +| --working-dirs | \[Optional\]

A comma separated list of relative working directories, to determine the audit targets locations. | +| --threads | \[Default: 10\]

The number of parallel threads used to determine the curation status for each package in the project tree. | | + +#### **Output Example** + +![image](images/jf-ca-output.png) + + +**Example 1** + +Audit the project in the current directory. Displays all known packages that were blocked by Curation Policies. + + jf curation-audit + +**Example 2** + +Audit the projects according to the specific paths defined in the "working-dirs" option. Displays all known packages that were blocked by Curation Policies for all projects. The data is displayed in separate tables. + + jf curation-audit --working-dirs="/path/to/project/npm_project1,/path/to/project/npm_project2" + +**Example 3** + +Audit the project in the current directory using 5 threads to check the packages Curation status in parallel. Displays all known packages blocked by Curation Policies. + + jf curation-audit --threads=5 diff --git a/documentation/cli.ftmap b/documentation/cli.ftmap index 2a967949b..b64bc4a40 100644 --- a/documentation/cli.ftmap +++ b/documentation/cli.ftmap @@ -16,5 +16,7 @@ + + diff --git a/documentation/images/jf-ca-output.png b/documentation/images/jf-ca-output.png new file mode 100644 index 0000000000000000000000000000000000000000..43b12a4b55fad5ea5510732d643438d9fbea46be GIT binary patch literal 102737 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

!^*7Ybe`tmG`}7Pb1N2pHCqyCi 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 Date: Wed, 12 Jul 2023 11:21:24 +0300 Subject: [PATCH 17/25] Fix CVersions (#2069) --- documentation/CLI-for-JFrog-Curation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/CLI-for-JFrog-Curation.md b/documentation/CLI-for-JFrog-Curation.md index d09a0113a..651068ab3 100644 --- a/documentation/CLI-for-JFrog-Curation.md +++ b/documentation/CLI-for-JFrog-Curation.md @@ -4,16 +4,16 @@ JFrog CLI : CLI for JFrog Curation Overview -------- -JFrog Curation enables you to block malicious or risky open-source packages entering your software supply chain, preventing consumption in any software pipeline. +JFrog Curation enables you to block malicious or risky open-source packages entering your software supply chain. What can you do with Curation? * Track the open-source packages downloaded by your organization to gain centralized visibility and control. * Prevent harmful packages from getting into your software development pipelines. * Protect against known and unknown threats, allowing only trusted software packages into your SDLC. * Create policies to block packages with known vulnerabilities, malicious code, operational risk, or license compliance issues. -For more information on JFrog Curation and how to set it up, see the JFrog Curation general documentation. +For more information on JFrog Curation and how to set it up, see the JFrog Curation general documentation at https://jfrog.com/help. -JFrog Curation requires [Xray version 3.78.9](https://jfrog.com/help/r/jfrog-release-information/xray-3.78.9) and above, and [Artifactory version 7.63.2](https://jfrog.com/help/r/jfrog-release-information/artifactory-7.63.2-cloud) and above. It also requires Enterprise X and Enterprise + subscriptions. +JFrog Curation requires [Xray version 3.78.9](https://jfrog.com/help/r/jfrog-release-information/xray-3.78.9) and above, and [Artifactory version 7.63.5](https://jfrog.com/help/r/jfrog-release-information/artifactory-7.63) and above. It also requires Enterprise X and Enterprise + subscriptions. --- From eafc78ce77c0ddf83aada4ff5782b4c688d72192 Mon Sep 17 00:00:00 2001 From: Robi Nino Date: Wed, 12 Jul 2023 16:44:32 +0300 Subject: [PATCH 18/25] Increase chocolatey publish retries (#2072) --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 16c3d1d27..3140b8ea2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -411,9 +411,9 @@ def publishNpmPackage(jfrogCliRepoDir) { } def publishChocoPackageWithRetries(version, jfrogCliRepoDir, architectures) { - def maxAttempts = 3 + def maxAttempts = 10 def currentAttempt = 1 - def waitSeconds = 20 + def waitSeconds = 18 while (currentAttempt <= maxAttempts) { try { From 752410f4d7d431f1bbf81de9fc6c9a87993d0c6d Mon Sep 17 00:00:00 2001 From: Asaf Ambar Date: Wed, 12 Jul 2023 18:59:10 +0300 Subject: [PATCH 19/25] Multi Policies support for JFrog Curation (#2060) --- go.mod | 2 +- go.sum | 9 ++------- scan/cli.go | 1 - xray_test.go | 14 +++++++++++--- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 54ef69c82..b741bfee2 100644 --- a/go.mod +++ b/go.mod @@ -123,7 +123,7 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230705084348-c7d33487e393 +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230711083838-491202db9c1e // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 diff --git a/go.sum b/go.sum index 4f993c508..11ab4a814 100644 --- a/go.sum +++ b/go.sum @@ -222,7 +222,6 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.5.3 h1:twfIhZs4QLCtimkP7MOxlF3A0U/5cDPseRT9M/+2SCE= github.com/gookit/color v1.5.3/go.mod h1:NUzwzeehUfl7GIb36pqId+UGmRfQcU/WiiyTTeNjHtE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -239,8 +238,8 @@ github.com/jfrog/build-info-go v1.9.6 h1:lCJ2j5uXAlJsSwDe5J8WD7Co1f/hUlZvMfwfb5A github.com/jfrog/build-info-go v1.9.6/go.mod h1:GbuFS+viHCKZYx9nWHYu7ab1DgQkFdtVN3BJPUNb2D4= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230705084348-c7d33487e393 h1:zIaBtAjalQ7HLwiYcR3OSU9Jglpmhtw8rg6piYervNU= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230705084348-c7d33487e393/go.mod h1:DnamqHWhKmrmWlCRG3i3z8Wn0JRtNFMC+Bu8TCFzSPY= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230711083838-491202db9c1e h1:jMyCGFyh7KjjF5Benqihsmb7NR8Zucxs65T5Xwwdd4k= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230711083838-491202db9c1e/go.mod h1:DnamqHWhKmrmWlCRG3i3z8Wn0JRtNFMC+Bu8TCFzSPY= github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228 h1:bkOkjb6sVqo6Jgw9eYSH58jIFPOJvFvwt+jIXvef7QM= github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -742,8 +741,6 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY= -google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -762,8 +759,6 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= -google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/scan/cli.go b/scan/cli.go index a407a0519..a99b94e1d 100644 --- a/scan/cli.go +++ b/scan/cli.go @@ -48,7 +48,6 @@ func GetCommands() []cli.Command { ArgsUsage: common.CreateEnvVars(), BashComplete: corecommondocs.CreateBashCompletionFunc(), Action: CurationCmd, - Hidden: true, }, { Name: "audit", diff --git a/xray_test.go b/xray_test.go index b469c9568..c55d46b76 100644 --- a/xray_test.go +++ b/xray_test.go @@ -725,8 +725,16 @@ func getCurationExpectedResponse(config *config.ServerDetails) []coreCuration.Pa PkgType: "npm", Policy: []coreCuration.Policy{ { - Policy: "pol1", - Condition: "cond1", + Policy: "pol1", + Condition: "cond1", + Explanation: "explanation", + Recommendation: "recommendation", + }, + { + Policy: "pol2", + Condition: "cond2", + Explanation: "explanation2", + Recommendation: "recommendation2", }, }, }, @@ -752,7 +760,7 @@ func curationServer(t *testing.T, expectedRequest map[string]bool, requestToFail w.WriteHeader(http.StatusForbidden) _, err := w.Write([]byte("{\n \"errors\": [\n {\n \"status\": 403,\n " + "\"message\": \"Package download was blocked by JFrog Packages " + - "Curation service due to the following policies violated {pol1, cond1}\"\n }\n ]\n}")) + "Curation service due to the following policies violated {pol1, cond1, explanation, recommendation}, {pol2, cond2, explanation2, recommendation2}\"\n }\n ]\n}")) require.NoError(t, err) } } From 3d49015b76144fd03ac8eb009e873d35b6f0b191 Mon Sep 17 00:00:00 2001 From: Omer Zidkoni <50792403+omerzi@users.noreply.github.com> Date: Wed, 12 Jul 2023 20:06:40 +0300 Subject: [PATCH 20/25] Promoted version to 2.43.0 (#2073) --- build/npm/v2-jf/package-lock.json | 2 +- build/npm/v2-jf/package.json | 2 +- build/npm/v2/package-lock.json | 2 +- build/npm/v2/package.json | 2 +- go.mod | 8 ++++---- go.sum | 8 ++++---- utils/cliutils/cli_consts.go | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index 6a02eeb2a..416e139e4 100644 --- a/build/npm/v2-jf/package-lock.json +++ b/build/npm/v2-jf/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.42.1", + "version": "2.43.0", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index eaef6b839..c669ef233 100644 --- a/build/npm/v2-jf/package.json +++ b/build/npm/v2-jf/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.42.1", + "version": "2.43.0", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/npm/v2/package-lock.json b/build/npm/v2/package-lock.json index 47f24e3de..1520f7b1a 100644 --- a/build/npm/v2/package-lock.json +++ b/build/npm/v2/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2", - "version": "2.42.1", + "version": "2.43.0", "lockfileVersion": 1 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index 0c66a040e..2225f9679 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.42.1", + "version": "2.43.0", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/go.mod b/go.mod index b741bfee2..36f39aade 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d github.com/jfrog/build-info-go v1.9.6 github.com/jfrog/gofrog v1.3.0 - github.com/jfrog/jfrog-cli-core/v2 v2.37.1 - github.com/jfrog/jfrog-client-go v1.31.0 + github.com/jfrog/jfrog-cli-core/v2 v2.38.0 + github.com/jfrog/jfrog-client-go v1.31.1 github.com/jszwec/csvutil v1.8.0 github.com/mholt/archiver/v3 v3.5.1 github.com/pkg/errors v0.9.1 @@ -123,8 +123,8 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230711083838-491202db9c1e +// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230705084348-c7d33487e393 // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228 +// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228 diff --git a/go.sum b/go.sum index 11ab4a814..e6f01b8bd 100644 --- a/go.sum +++ b/go.sum @@ -238,10 +238,10 @@ github.com/jfrog/build-info-go v1.9.6 h1:lCJ2j5uXAlJsSwDe5J8WD7Co1f/hUlZvMfwfb5A github.com/jfrog/build-info-go v1.9.6/go.mod h1:GbuFS+viHCKZYx9nWHYu7ab1DgQkFdtVN3BJPUNb2D4= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230711083838-491202db9c1e h1:jMyCGFyh7KjjF5Benqihsmb7NR8Zucxs65T5Xwwdd4k= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230711083838-491202db9c1e/go.mod h1:DnamqHWhKmrmWlCRG3i3z8Wn0JRtNFMC+Bu8TCFzSPY= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228 h1:bkOkjb6sVqo6Jgw9eYSH58jIFPOJvFvwt+jIXvef7QM= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= +github.com/jfrog/jfrog-cli-core/v2 v2.38.0 h1:lHylMjp0+IbZAUKVWi++keVktpyvI/0UwewIdbCoI/A= +github.com/jfrog/jfrog-cli-core/v2 v2.38.0/go.mod h1:Ws5UvSUITSZGuVVNNb/lDFPG0UAyiwpKv5o86M8By9I= +github.com/jfrog/jfrog-client-go v1.31.1 h1:lmunA5ZpRsrWTXgEGvnvVPIfwEqB3gn6+eVNpV2VBzU= +github.com/jfrog/jfrog-client-go v1.31.1/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index 9ce4b4c2c..79b624260 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -4,7 +4,7 @@ import "time" const ( // General CLI constants - CliVersion = "2.42.1" + CliVersion = "2.43.0" ClientAgent = "jfrog-cli-go" // CLI base commands constants: From cbcfbf6edb717756d7168a6c27cfc889731f46c9 Mon Sep 17 00:00:00 2001 From: Eyal Ben Moshe Date: Wed, 12 Jul 2023 21:20:50 +0300 Subject: [PATCH 21/25] Promote to version 2.43.1 (#2074) --- build/npm/v2-jf/package-lock.json | 2 +- build/npm/v2-jf/package.json | 2 +- build/npm/v2/package-lock.json | 2 +- build/npm/v2/package.json | 2 +- utils/cliutils/cli_consts.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index 416e139e4..c0b4385bc 100644 --- a/build/npm/v2-jf/package-lock.json +++ b/build/npm/v2-jf/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.43.0", + "version": "2.43.1", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index c669ef233..9a29ffc90 100644 --- a/build/npm/v2-jf/package.json +++ b/build/npm/v2-jf/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.43.0", + "version": "2.43.1", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/npm/v2/package-lock.json b/build/npm/v2/package-lock.json index 1520f7b1a..66de95f85 100644 --- a/build/npm/v2/package-lock.json +++ b/build/npm/v2/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2", - "version": "2.43.0", + "version": "2.43.1", "lockfileVersion": 1 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index 2225f9679..cfaa4c69b 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.43.0", + "version": "2.43.1", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index 79b624260..b0f699b5b 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -4,7 +4,7 @@ import "time" const ( // General CLI constants - CliVersion = "2.43.0" + CliVersion = "2.43.1" ClientAgent = "jfrog-cli-go" // CLI base commands constants: From ef7f99c378d38ca4fe1502293e2e643302ad6017 Mon Sep 17 00:00:00 2001 From: Robi Nino Date: Thu, 13 Jul 2023 16:36:06 +0300 Subject: [PATCH 22/25] Respect project env var on build discard and promote (#2076) --- artifactory/cli.go | 16 ++++++++-------- buildtools/cli.go | 8 +------- utils/cliutils/utils.go | 17 ++++++++++++----- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/artifactory/cli.go b/artifactory/cli.go index 11e7474c2..065205971 100644 --- a/artifactory/cli.go +++ b/artifactory/cli.go @@ -1029,7 +1029,7 @@ func containerPushCmd(c *cli.Context, containerManagerType containerutils.Contai targetRepo := c.Args().Get(1) skipLogin := c.Bool("skip-login") - buildConfiguration, err := buildtools.CreateBuildConfigurationWithModule(c) + buildConfiguration, err := cliutils.CreateBuildConfigurationWithModule(c) if err != nil { return } @@ -1064,7 +1064,7 @@ func containerPullCmd(c *cli.Context, containerManagerType containerutils.Contai imageTag := c.Args().Get(0) sourceRepo := c.Args().Get(1) skipLogin := c.Bool("skip-login") - buildConfiguration, err := buildtools.CreateBuildConfigurationWithModule(c) + buildConfiguration, err := cliutils.CreateBuildConfigurationWithModule(c) if err != nil { return err } @@ -1090,7 +1090,7 @@ func BuildDockerCreateCmd(c *cli.Context) error { if imageNameWithDigestFile == "" { return cliutils.PrintHelpAndReturnError("The '--image-file' command option was not provided.", c) } - buildConfiguration, err := buildtools.CreateBuildConfigurationWithModule(c) + buildConfiguration, err := cliutils.CreateBuildConfigurationWithModule(c) if err != nil { return err } @@ -1217,7 +1217,7 @@ func downloadCmd(c *cli.Context) error { if err != nil { return err } - buildConfiguration, err := buildtools.CreateBuildConfigurationWithModule(c) + buildConfiguration, err := cliutils.CreateBuildConfigurationWithModule(c) if err != nil { return err } @@ -1274,7 +1274,7 @@ func uploadCmd(c *cli.Context) (err error) { if err != nil { return } - buildConfiguration, err := buildtools.CreateBuildConfigurationWithModule(c) + buildConfiguration, err := cliutils.CreateBuildConfigurationWithModule(c) if err != nil { return } @@ -1298,7 +1298,7 @@ func uploadCmd(c *cli.Context) (err error) { "You can avoid this confirmation message by adding --quiet to the command.", false) { return nil } - // This error is being checked latter on because we need to generate summary report before return. + // This error is being checked later on because we need to generate summary report before return. err = progressbar.ExecWithProgress(uploadCmd) result := uploadCmd.Result() defer cliutils.CleanupResult(result, &err) @@ -2529,7 +2529,7 @@ func createBuildPromoteConfiguration(c *cli.Context) services.PromotionParams { promotionParamsImpl.IncludeDependencies = c.Bool("include-dependencies") promotionParamsImpl.Copy = c.Bool("copy") promotionParamsImpl.Properties = c.String("props") - promotionParamsImpl.ProjectKey = c.String("project") + promotionParamsImpl.ProjectKey = cliutils.GetProject(c) promotionParamsImpl.FailFast = c.BoolT("fail-fast") // If the command received 3 args, read the build name, build number @@ -2554,7 +2554,7 @@ func createBuildDiscardConfiguration(c *cli.Context) services.DiscardBuildsParam discardParamsImpl.ExcludeBuilds = c.String("exclude-builds") discardParamsImpl.Async = c.Bool("async") discardParamsImpl.BuildName = cliutils.GetBuildName(c.Args().Get(0)) - discardParamsImpl.ProjectKey = c.String("project") + discardParamsImpl.ProjectKey = cliutils.GetProject(c) return discardParamsImpl } diff --git a/buildtools/cli.go b/buildtools/cli.go index 4d1f9762d..ce2c438ea 100644 --- a/buildtools/cli.go +++ b/buildtools/cli.go @@ -629,7 +629,7 @@ func GoPublishCmd(c *cli.Context) (err error) { if err != nil { return err } - buildConfiguration, err := CreateBuildConfigurationWithModule(c) + buildConfiguration, err := cliutils.CreateBuildConfigurationWithModule(c) if err != nil { return err } @@ -663,12 +663,6 @@ func goCmdVerification(c *cli.Context) (string, error) { return configFilePath, nil } -func CreateBuildConfigurationWithModule(c *cli.Context) (buildConfigConfiguration *utils.BuildConfiguration, err error) { - buildConfigConfiguration = new(utils.BuildConfiguration) - err = buildConfigConfiguration.SetBuildName(c.String("build-name")).SetBuildNumber(c.String("build-number")).SetProject(c.String("project")).SetModule(c.String("module")).ValidateBuildAndModuleParams() - return -} - func dockerCmd(c *cli.Context) error { args := cliutils.ExtractCommand(c) var cmd, image string diff --git a/utils/cliutils/utils.go b/utils/cliutils/utils.go index ffcfe7558..daae7887b 100644 --- a/utils/cliutils/utils.go +++ b/utils/cliutils/utils.go @@ -725,7 +725,8 @@ func SetCliExecutableName(executablePath string) { coreutils.SetCliExecutableName(filepath.Base(executablePath)) } -// Returns build configuration struct using the params provided from the console. +// Returns build configuration struct using the args (build name/number) and options (project) provided by the user. +// Any empty configuration could be later overridden by environment variables if set. func CreateBuildConfiguration(c *cli.Context) *artifactoryUtils.BuildConfiguration { buildConfiguration := new(artifactoryUtils.BuildConfiguration) buildNameArg, buildNumberArg := c.Args().Get(0), c.Args().Get(1) @@ -737,6 +738,15 @@ func CreateBuildConfiguration(c *cli.Context) *artifactoryUtils.BuildConfigurati return buildConfiguration } +// Returns build configuration struct using the options provided by the user. +// Any empty configuration could be later overridden by environment variables if set. +func CreateBuildConfigurationWithModule(c *cli.Context) (buildConfigConfiguration *artifactoryUtils.BuildConfiguration, err error) { + buildConfigConfiguration = new(artifactoryUtils.BuildConfiguration) + err = buildConfigConfiguration.SetBuildName(c.String("build-name")).SetBuildNumber(c.String("build-number")). + SetProject(c.String("project")).SetModule(c.String("module")).ValidateBuildAndModuleParams() + return +} + func CreateArtifactoryDetailsByFlags(c *cli.Context) (*coreConfig.ServerDetails, error) { artDetails, err := CreateServerDetailsWithConfigOffer(c, false, Rt) if err != nil { @@ -860,8 +870,5 @@ func doHttpRequest(client *http.Client, req *http.Request) (resp *http.Response, // Get project key from flag or environment variable func GetProject(c *cli.Context) string { projectKey := c.String("project") - if projectKey == "" { - projectKey = os.Getenv(coreutils.Project) - } - return projectKey + return getOrDefaultEnv(projectKey, coreutils.Project) } From 95f6f4a8eae424f894c413887363c7d855f010c9 Mon Sep 17 00:00:00 2001 From: Yahav Itzhak Date: Fri, 14 Jul 2023 18:29:20 +0300 Subject: [PATCH 23/25] Add CONTRIBUTING.md (#2078) --- .github/PULL_REQUEST_TEMPLATE.md | 11 +- CONTRIBUTING.md | 297 ++++++++++++++++++++++++++++ README.md | 321 +------------------------------ 3 files changed, 305 insertions(+), 324 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f10575440..cca3d0c4e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,5 +1,6 @@ -- [ ] All [tests](https://github.com/jfrog/jfrog-cli#tests) passed. If this feature is not already covered by the tests, I added new tests. -- [ ] All [static analysis checks](https://github.com/jfrog/jfrog-cli/actions/workflows/analysis.yml) passed. -- [ ] This pull request is on the dev branch. -- [ ] I used gofmt for formatting the code before submitting the pull request. ------ +- [ ] All [tests](https://github.com/jfrog/jfrog-cli/CONTRIBUTING.md#tests) have passed. If this feature is not already covered by the tests, new tests have been added. +- [ ] The pull request is targeting the `dev` branch. +- [ ] The code has been validated to compile successfully by running `go vet ./...`. +- [ ] The code has been formatted properly using `go fmt ./...`. + +--- diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..d9bd3949d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,297 @@ +# 📖 Guidelines + +- Ensure that your changes are covered by existing tests. If not, please add new tests. +- Create pull requests on the `dev` branch. +- Before submitting the pull request, format the code by running `go fmt ./...`. +- Before submitting the pull request, ensure the code compiles by running `go vet ./...`. + +# ⚒️ Building and Testing the Sources + +## Building JFrog CLI + +To build JFrog CLI, first, make sure Go is installed by running the following command: + +```sh +go version +``` + +Next, clone the project sources and navigate to the root directory: + +```sh +git clone https://github.com/jfrog/jfrog-cli.git +cd jfrog-cli +``` + +To build the sources on Unix-based systems, run: + +```sh +./build/build.sh +``` + +On Windows, run: + +```sh +.\build\build.bat +``` + +After the build process completes, you will find the `jf` or `jf.exe` executable in the current directory. + +### Dependencies in other JFrog modules + +This project heavily depends on the following modules: + +- [github.com/jfrog/jfrog-client-go](https://github.com/jfrog/jfrog-client-go) +- [github.com/jfrog/jfrog-cli-core](github.com/jfrog/jfrog-cli-core) +- [github.com/jfrog/build-info-go](github.com/jfrog/build-info-go) +- [github.com/jfrog/gofrog](github.com/jfrog/gofrog) + +#### Local Development + +During local development, if you come across code that needs to be modified in one of the mentioned modules, it is advisable to replace the dependency with a local clone of the module. + +For instance, let's assume you wish to modify files from `jfrog-cli-core`. Clone the `jfrog-cli-core` repository (preferably your fork) to your local development machine, placing it at `/local/path/in/your/machine/jfrog-cli-core`. + +To include this local dependency, modify the `go.mod` file as follows: + +``` +replace github.com/jfrog/jfrog-cli-core/v2 => /local/path/in/your/machine/jfrog-cli-core +``` + +Afterward, execute `go mod tidy` to ensure the Go module files are updated. Note that Go will automatically adjust the version in the `go.mod` file. + +#### Pull Requests + +Once you have completed your coding changes, it is recommended to push the modifications made to the other modules first. Once these changes are pushed, you can update this project to resolve dependencies from your GitHub fork or branch. To achieve this, modify the `go.mod` file to point the dependency to your repository and branch, as shown in the example below: + +``` +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/galusben/jfrog-cli-core/v2 dev +``` + +Finally, execute `go mod tidy` to update the Go module files. Please note that Go will automatically update the version in the `go.mod` file. + +## Tests + +### Usage + +To run tests, use the following command: + +``` +go test -v github.com/jfrog/jfrog-cli [test-types] [flags] +``` + +The available flags are: + +| Flag | Description | +| ------------------- | ----------------------------------------------------------------------------------------------- | +| `-jfrog.url` | [Default: http://localhost:8081] JFrog platform URL | +| `-jfrog.user` | [Default: admin] JFrog platform username | +| `-jfrog.password` | [Default: password] JFrog platform password | +| `-jfrog.adminToken` | [Optional] JFrog platform admin token | +| `-ci.runId` | [Optional] A unique identifier used as a suffix to create repositories and builds in the tests. | + +The available test types are: + +| Type | Description | +| -------------------- | ------------------ | +| `-test.artifactory` | Artifactory tests | +| `-test.access` | Access tests | +| `-test.npm` | Npm tests | +| `-test.maven` | Maven tests | +| `-test.gradle` | Gradle tests | +| `-test.docker` | Docker tests | +| `-test.dockerScan` | Docker scan tests | +| `-test.podman` | Podman tests | +| `-test.go` | Go tests | +| `-test.pip` | Pip tests | +| `-test.pipenv` | Pipenv tests | +| `-test.poetry` | Poetry tests | +| `-test.nuget` | Nuget tests | +| `-test.plugins` | Plugins tests | +| `-test.distribution` | Distribution tests | +| `-test.transfer` | Transfer tests | +| `-test.xray` | Xray tests | + +When running the tests, builds and repositories with timestamps will be created, for example: `cli-rt1-1592990748` and `cli-rt2-1592990748`. The content of these repositories will be deleted once the tests are completed. + +#### Artifactory tests + +In addition to the [general optional flags](#Usage), you can use the following optional Artifactory flags: + +| Flag | Description | +| ---------------------- | --------------------------------------------------------------------------------------------------------------- | +| `-jfrog.sshKeyPath` | [Optional] Path to the SSH key file. Use this flag only if the Artifactory URL format is `ssh://[domain]:port`. | +| `-jfrog.sshPassphrase` | [Optional] Passphrase for the SSH key. | + +##### Examples + +To run Artifactory tests, execute the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.artifactory [flags] +``` + +#### Npm tests + +##### Requirements + +- The _npm_ executables should be included in the system's `PATH` environment variable. +- The tests are compatible with npm 7 and higher. + +##### Limitations + +- Currently, npm integration only supports HTTP(S) connections to Artifactory using username and password. + +##### Examples + +To run Npm tests, execute the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.npm [flags] +``` + +#### Maven tests + +##### Requirements + +- The _java_ executable should be included in the system's `PATH` environment variable. Alternatively, set the `_JAVA_HOME` environment variable. + +##### Limitations + +- Currently, Maven integration only supports HTTP(S) connections to Artifactory using username and password. + +##### Examples + +To run Maven tests, execute the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.maven [flags] +``` + +#### Gradle tests + +##### Requirements + +- The _gradle_ and _java_ executables should be included in the system's `PATH` environment variable. Alternatively, set the `JAVA_HOME` environment variable. + +##### Limitations + +- Currently, Gradle integration only supports HTTP(S) connections to Artifactory using username and password. + +##### Examples + +To run Gradle tests, execute the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.gradle [flags] +``` + +#### Docker tests + +##### Requirements + +- Make sure the `RTLIC` environment variable is configured with a valid license. +- You can start an Artifactory container by running the `startArtifactory.sh` script located in the `testdata/docker/artifactory` directory. Before running the tests, wait for Artifactory to finish booting up in the container. + +| Flag | Description | +| ------------------------- | ----------------------------------- | +| `-test.containerRegistry` | Artifactory Docker registry domain. | + +##### Examples + +To run Docker tests, execute the following command (replace the missing parameters as described below): + +``` +go test -v github.com/jfrog/jfrog-cli -test.docker [flags] +``` + +#### Podman tests + +| Flag | Description | +| ------------------------- | -------------------------------------- | +| `-test.containerRegistry` | Artifactory container registry domain. | + +##### Examples + +To run Podman tests, execute the following command (replace the missing parameters as described below): + +``` +go test -v github.com/jfrog/jfrog-cli -test.podman [flags] +``` + +#### Go commands tests + +##### + +Requirements + +- The tests are compatible with Artifactory 6.10 and higher. +- To run Go tests, use the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.go [flags] +``` + +#### NuGet tests + +##### Requirements + +- Add the NuGet executable to the system's `PATH` environment variable. +- Run the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.nuget [flags] +``` + +#### Pip tests + +##### Requirements + +- Add the Python and pip executables to the system's `PATH` environment variable. +- Run the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.pip [flags] +``` + +#### Plugins tests + +To run Plugins tests, execute the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.plugins +``` + +#### Distribution tests + +To run Distribution tests, execute the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.distribution [flags] +``` + +#### Transfer tests + +##### Requirement + +The Transfer tests execute `transfer-files` commands between a local Artifactory server and a remote SaaS instance. In addition to the [general optional flags](#Usage), you _must_ use the following flags: + +| Flag | Description | +| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `-jfrog.targetUrl` | JFrog target platform URL. | +| `-jfrog.targetAdminToken` | JFrog target platform admin token. | +| `-jfrog.jfrogHome` | The JFrog home directory of the local Artifactory installation. | +| `-jfrog.installDataTransferPlugin` | Set this flag to `true` if you want the test to automatically install the data-transfer plugin in the source Artifactory server. | + +To run Transfer tests, execute the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.transfer [flags] +``` + +### Xray tests + +To run Xray tests, execute the following command: + +``` +go test -v github.com/jfrog/jfrog-cli -test.xray -test.dockerScan [flags] +``` diff --git a/README.md b/README.md index c6112be75..16955cb4e 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/jfrog/jfrog-cli)](https://goreportcard.com/report/github.com/jfrog/jfrog-cli) [![license](https://img.shields.io/badge/License-Apache_2.0-blue.svg?style=flat)](https://raw.githubusercontent.com/jfrog/jfrog-cli/v2/LICENSE) [![](https://img.shields.io/badge/Docs-%F0%9F%93%96-blue)](https://www.jfrog.com/confluence/display/CLI/JFrog+CLI) [![Go version](https://img.shields.io/github/go-mod/go-version/jfrog/jfrog-cli)](https://tip.golang.org/doc/go1.20) +

@@ -235,8 +236,6 @@ - [Overview](#overview) - [Download and Installation](#download-and-installation) -- [Building the Executable](#building-the-executable) -- [Tests](#tests) - [Code Contributions](#code-contributions) - [Using JFrog CLI](#using-jfrog-cli) - [JFrog CLI Plugins](#jfrog-cli-plugins) @@ -260,325 +259,9 @@ Several features of the JFrog CLI makes your scripts more efficient and reliable You can either install JFrog CLI using one of the supported installers or download its executable directly. Visit the [Install JFrog CLI Page](https://jfrog.com/getcli/) for details. -# Building the Executable - -JFrog CLI is written in the [Go programming language](https://golang.org/), so to build the CLI yourself, you first need -to have Go installed and configured on your machine. - -## Install Go - -To download and install `Go`, please refer to the [Go documentation](https://golang.org/doc/install). -Please download `Go 1.14.x` or above. - -## Download and Build the CLI - -Navigate to a directory where you want to create the jfrog-cli project, **outside** the `$GOPATH` tree. - -If the `GOPATH` variable is unset, it's default value is the go folder under the user home. - -Verify that the `GO111MODULE` variable is either unset, or explicitly set to `auto`. - -Clone the jfrog-cli project by executing the following command: - -``` -git clone https://github.com/jfrog/jfrog-cli -``` - -Build the project by navigating to the jfrog folder and executing the following commands. -On Unix based systems run: - -``` -cd jfrog-cli -build/build.sh -``` - -On Windows run: - -``` -cd jfrog-cli -build\build.bat -``` - -Once completed, you will find the JFrog CLI executable at your current directory. - -# Tests - -### Usage - -``` -go test -v github.com/jfrog/jfrog-cli [test-types] [flags] -``` - -The flags are: - -| Flag | Description | -|---------------------|-------------------------------------------------------------------------------------------------| -| `-jfrog.url` | [Default: http://localhost:8081] JFrog platform URL. | -| `-jfrog.user` | [Default: admin] JFrog platform username. | -| `-jfrog.password` | [Default: password] JFrog platform password. | -| `-jfrog.adminToken` | [Optional] JFrog platform admin token. | -| `-ci.runId` | [Optional] A unique identifier used as a suffix to create repositories and builds in the tests. | - -The types are: - -| Type | Description | -|----------------------|--------------------| -| `-test.artifactory` | Artifactory tests | -| `-test.access` | Access tests | -| `-test.npm` | Npm tests | -| `-test.maven` | Maven tests | -| `-test.gradle` | Gradle tests | -| `-test.docker` | Docker tests | -| `-test.dockerScan` | Docker scan tests | -| `-test.podman` | Podman tests | -| `-test.go` | Go tests | -| `-test.pip` | Pip tests | -| `-test.pipenv` | Pipenv tests | -| `-test.poetry` | Poetry tests | -| `-test.nuget` | Nuget tests | -| `-test.plugins` | Plugins tests | -| `-test.distribution` | Distribution tests | -| `-test.transfer` | Transfer tests | -| `-test.xray` | Xray tests | - -- Running the tests will create builds and repositories with timestamps, - for example: `cli-rt1-1592990748` and `cli-rt2-1592990748`.
- Once the tests are completed, the content of these repositories will be deleted. - -#### Artifactory tests - -In addition to [general optional flags](#Usage) you can use the following optional artifactory flags. - -| Flag | Description | -|------------------------|---------------------------------------------------------------------------------------------------------| -| `-jfrog.sshKeyPath` | [Optional] Ssh key file path. Should be used only if the Artifactory URL format is ssh://[domain]:port. | -| `-jfrog.sshPassphrase` | [Optional] Ssh key passphrase. | - -##### Examples - -To run artifactory tests execute the following command. - -``` -go test -v github.com/jfrog/jfrog-cli -test.artifactory [flags] -``` - -#### Npm tests - -##### Requirements - -- The _npm_ executables should be included as part of the _PATH_ environment variable. -- The tests are compatible with npm 7 and higher. - -##### Limitation - -- Currently, npm integration support only http(s) connections to Artifactory using username and password. - -##### Examples - -To run npm tests execute the following command. - -``` -go test -v github.com/jfrog/jfrog-cli -test.npm [flags] -``` - -#### Maven tests - -##### Requirements - -- The _java_ executable should be included as part of the _PATH_ environment variable. Alternatively, set the - _JAVA_HOME_ environment variable. - -##### Limitation - -- Currently, maven integration support only http(s) connections to Artifactory using username and password. - -##### Examples - -To run maven tests execute the following command. - -``` -go test -v github.com/jfrog/jfrog-cli -test.maven [flags] -``` - -#### Gradle tests - -##### Requirements - -- The _gradle_ executables should be included as part of the _PATH_ environment variable. -- The _java_ executable should be included as part of the _PATH_ environment variable. Alternatively, set the - _JAVA_HOME_ environment variable. - -##### Limitation - -- Currently, gradle integration support only http(s) connections to Artifactory using username and password. - -##### Examples - -To run gradle tests execute the following command. - -``` -go test -v github.com/jfrog/jfrog-cli -test.gradle [flags] -``` - -#### Docker tests - -##### Requirements - -- Make sure the environment variable `RTLIC` is configured with a valid license. -- You can start an Artifactory container by running the `startArtifactory.sh` script under - the `testdata/docker/artifactory` directory. Before running the tests, wait for Artifactory to finish booting up in - the container. - -| Flag | Description | -|---------------------------|-------------------------------------| -| `-test.containerRegistry` | Artifactory Docker registry domain. | - -##### Examples - -To run docker tests execute the following command (fill out the missing parameters as described below). - -``` -go test -v github.com/jfrog/jfrog-cli -test.docker [flags] -``` - -#### Podman tests - -| Flag | Description | -|---------------------------|----------------------------------------| -| `-test.containerRegistry` | Artifactory container registry domain. | - -##### Examples - -To run podman tests execute the following command (fill out the missing parameters as described below). - -``` -go test -v github.com/jfrog/jfrog-cli -test.podman [flags] -``` - -#### Go commands tests - -##### Requirements - -- The tests are compatible with Artifactory 6.10 and higher. -- To run go tests run the following command: - -``` -go test -v github.com/jfrog/jfrog-cli -test.go [flags] -``` - -#### NuGet tests - -##### Requirements - -- Add NuGet executable to the system search path (PATH environment variable). -- Run the following command: - -``` -go test -v github.com/jfrog/jfrog-cli -test.nuget [flags] -``` - -#### Pip tests - -##### Requirements - -- Add Python and pip executables to the system search path (PATH environment variable). -- Run the following command: - -``` -go test -v github.com/jfrog/jfrog-cli -test.pip [flags] -``` - -#### Plugins tests - -To run Plugins tests execute the following command: - -``` -go test -v github.com/jfrog/jfrog-cli -test.plugins -``` - -### Distribution tests - -To run Distribution tests execute the following command: - -``` -go test -v github.com/jfrog/jfrog-cli -test.distribution [flags] -``` - -### Transfer tests - -##### Requirement - -The transfer tests execute `transfer-files` commands between a local Artifactory server and a remote SaaS instance. -In addition to [general optional flags](#Usage) you _must_ use the following flags: - -| Flag | Description | -|------------------------------------|----------------------------------------------------------------------------------------------------------------| -| `-jfrog.targetUrl` | JFrog target platform URL. | -| `-jfrog.targetAdminToken` | JFrog target platform admin token. | -| `-jfrog.jfrogHome` | The JFrog home directory of the local Artifactory installation. | -| `-jfrog.installDataTransferPlugin` | Set to true if you'd like the test to install the data-transfer automatically in the source Artifactory server | - -To run transfer tests execute the following command: - -``` -go test -v github.com/jfrog/jfrog-cli -test.transfer [flags] -``` - -### Xray tests - -To run Xray tests execute the following command: - -``` -go test -v github.com/jfrog/jfrog-cli -test.xray -test.dockerScan [flags] -``` - # Code Contributions -We welcome code contributions through pull requests from the community. - -## Pull Requests Guidelines - -- If the existing tests do not already cover your changes, please add tests.. -- Pull requests should be created on the _dev_ branch. -- Please use [gofmt](https://golang.org/cmd/gofmt/) for formatting the code before submitting the pull request. - -## Dependencies in other JFrog modules - -This project heavily depends on: - -- github.com/jfrog/jfrog-client-go -- github.com/jfrog/build-info-go -- github.com/jfrog/jfrog-cli-core - -### Local Development - -During local development, when you encounter code that needs to be changed from one of the above modules, it is -recommended to replace the dependency to work with a local clone of the dependency. - -For example, assuming you would like to change files from jfrog-cli-core. -Clone jfrog-cli-core (preferably your fork) to your local development machine -(assuming it will be cloned to `/repos/jfrog-cli-core`). - -Change go.mod to include the following: - -``` -replace github.com/jfrog/jfrog-cli-core/v2 => /repos/jfrog-cli-core -``` - -### Pull Requests - -Once done with your coding, you should push the changes you made to the other modules first. Once pushed, you can change -this -project to resolve the dependencies from your GitHub fork / branch. -This is done by pointing the dependency in go.mod to your repository and branch. For example: - -``` -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/galusben/jfrog-cli-core/v2 dev -``` - -Then run `go mod tidy` - -Notice that go will change the version in the go.mod file. +We welcome pull requests from the community. To help us improve this project, please read our [contribution](CONTRIBUTING.md) guide. # Using JFrog CLI From 488e89bb319a8cced2db20d3b1c9a9544a5204bf Mon Sep 17 00:00:00 2001 From: Sara Omari <114062096+sarao1310@users.noreply.github.com> Date: Mon, 17 Jul 2023 17:16:13 +0300 Subject: [PATCH 24/25] New `exclusions` options for go-publish (#2044) * gp --exclusion new flag --- buildtools/cli.go | 2 +- go.mod | 4 +- go.sum | 9 +-- go_test.go | 50 +++++++++++++ .../filespecs/go_publish_repo_excludes.json | 7 ++ testdata/go/project3/.jfrog/projects/go.yaml | 9 +++ .../go/project3/createGoProject_go.mod_suffix | 8 +++ testdata/go/project3/dependency.go | 11 +++ testdata/go/project3/go.sum | 7 ++ testdata/go/project4/.jfrog/projects/go.yaml | 9 +++ .../go/project4/createGoProject_go.mod_suffix | 8 +++ testdata/go/project4/dependency.go | 11 +++ testdata/go/project4/dir1/a.txt | 1 + testdata/go/project4/dir1/dir2/b.txt | 1 + testdata/go/project4/dir1/dir2/dir3/c.txt | 1 + testdata/go/project4/dir4/d.txt | 1 + testdata/go/project4/go.sum | 7 ++ utils/cliutils/commandsflags.go | 9 ++- utils/tests/consts.go | 71 +++++++++++++++++++ xray_test.go | 2 +- 20 files changed, 219 insertions(+), 9 deletions(-) create mode 100644 testdata/filespecs/go_publish_repo_excludes.json create mode 100644 testdata/go/project3/.jfrog/projects/go.yaml create mode 100644 testdata/go/project3/createGoProject_go.mod_suffix create mode 100644 testdata/go/project3/dependency.go create mode 100644 testdata/go/project3/go.sum create mode 100644 testdata/go/project4/.jfrog/projects/go.yaml create mode 100644 testdata/go/project4/createGoProject_go.mod_suffix create mode 100644 testdata/go/project4/dependency.go create mode 100644 testdata/go/project4/dir1/a.txt create mode 100644 testdata/go/project4/dir1/dir2/b.txt create mode 100644 testdata/go/project4/dir1/dir2/dir3/c.txt create mode 100644 testdata/go/project4/dir4/d.txt create mode 100644 testdata/go/project4/go.sum diff --git a/buildtools/cli.go b/buildtools/cli.go index ce2c438ea..508edb996 100644 --- a/buildtools/cli.go +++ b/buildtools/cli.go @@ -636,7 +636,7 @@ func GoPublishCmd(c *cli.Context) (err error) { version := c.Args().Get(0) printDeploymentView, detailedSummary := log.IsStdErrTerminal(), c.Bool("detailed-summary") goPublishCmd := golang.NewGoPublishCommand() - goPublishCmd.SetConfigFilePath(configFilePath).SetBuildConfiguration(buildConfiguration).SetVersion(version).SetDetailedSummary(detailedSummary || printDeploymentView) + goPublishCmd.SetConfigFilePath(configFilePath).SetBuildConfiguration(buildConfiguration).SetVersion(version).SetDetailedSummary(detailedSummary || printDeploymentView).SetExcludedPatterns(cliutils.GetStringsArrFlagValue(c, "exclusions")) err = commands.Exec(goPublishCmd) result := goPublishCmd.Result() defer cliutils.CleanupResult(result, &err) diff --git a/go.mod b/go.mod index 36f39aade..a31b5d245 100644 --- a/go.mod +++ b/go.mod @@ -123,8 +123,8 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go -// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230705084348-c7d33487e393 +replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230717092920-cd976eb1e5c3 // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230705083849-6fd087a5e228 +replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230717090738-b2e0c7bcc026 diff --git a/go.sum b/go.sum index e6f01b8bd..a9953b121 100644 --- a/go.sum +++ b/go.sum @@ -238,10 +238,10 @@ github.com/jfrog/build-info-go v1.9.6 h1:lCJ2j5uXAlJsSwDe5J8WD7Co1f/hUlZvMfwfb5A github.com/jfrog/build-info-go v1.9.6/go.mod h1:GbuFS+viHCKZYx9nWHYu7ab1DgQkFdtVN3BJPUNb2D4= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.38.0 h1:lHylMjp0+IbZAUKVWi++keVktpyvI/0UwewIdbCoI/A= -github.com/jfrog/jfrog-cli-core/v2 v2.38.0/go.mod h1:Ws5UvSUITSZGuVVNNb/lDFPG0UAyiwpKv5o86M8By9I= -github.com/jfrog/jfrog-client-go v1.31.1 h1:lmunA5ZpRsrWTXgEGvnvVPIfwEqB3gn6+eVNpV2VBzU= -github.com/jfrog/jfrog-client-go v1.31.1/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230717092920-cd976eb1e5c3 h1:ED7QzMz/KA/7ps2bNvRiWbqBP/BbExWlUrJWcAoGiHM= +github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230717092920-cd976eb1e5c3/go.mod h1:QjTOL5xFgplonx47OnXXXurRtpQGDquGmrTbpe011EY= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230717090738-b2e0c7bcc026 h1:Xam/SD9ZqanqexbX2iW2H1fH5MLB9qx6vN8SK8wBMhA= +github.com/jfrog/jfrog-client-go v1.28.1-0.20230717090738-b2e0c7bcc026/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= @@ -674,6 +674,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/go_test.go b/go_test.go index d51d422ff..1b00960c0 100644 --- a/go_test.go +++ b/go_test.go @@ -203,6 +203,56 @@ func TestGoPublishWithDeploymentView(t *testing.T) { clientTestUtils.ChangeDirAndAssert(t, wd) } +func TestGoPublishWithExclusions(t *testing.T) { + _, goCleanupFunc := initGoTest(t) + defer goCleanupFunc() + wd, err := os.Getwd() + assert.NoError(t, err, "Failed to get current dir") + searchFilePath, err := tests.CreateSpec(tests.GoPublishRepoExcludes) + assert.NoError(t, err) + + var testData = []struct { + exclusions string + expectedExistFilesPaths []string + expectedNotExistFilesPaths []string + }{ + {"./dir1/*", tests.GetGoPublishWithExclusionsExpectedFiles1(), tests.GetGoPublishWithExclusionsExcludedFiles1()}, + {"./dir1/dir2/*", tests.GetGoPublishWithExclusionsExpectedFiles2(), tests.GetGoPublishWithExclusionsExcludedFiles2()}, + {"*.txt", nil, tests.GetGoPublishWithExclusionsExcludedFiles3()}, + } + for _, test := range testData { + prepareGoProject("project4", t, true) + jfrogCli := tests.NewJfrogCli(execMain, "jf", "") + err = execGo(jfrogCli, "gp", "v1.1.1", "--exclusions", test.exclusions) + assert.NoError(t, err) + + // Verify that go-publish successfully published expected files and directories to Artifactory. + inttestutils.VerifyExistInArtifactory(tests.GetGoPublishWithExclusionsExpectedRepoGo(), searchFilePath, serverDetails, t) + // Creating a temporary directory to download for it the content of the zip file from artifactory. + tmpDir, createTempDirCallback := coretests.CreateTempDirWithCallbackAndAssert(t) + err = os.RemoveAll(tmpDir) + assert.NoError(t, err) + assert.NoError(t, os.Mkdir(tmpDir, 0777)) + runRt(t, "download", tests.GoRepo, tmpDir+"/", "--explode") + // Checking whether the expected files exist in the zip file after downloading from artifactory with unzipping it. + for _, path := range test.expectedExistFilesPaths { + result, err := fileutils.IsFileExists(filepath.Join(tmpDir, path), true) + assert.NoError(t, err) + assert.True(t, result, "This file"+path+"does not exist") + } + // Checking whether the excluded files do not exist in the zip file after downloading from Artifactory with unzipping it. + for _, path := range test.expectedNotExistFilesPaths { + result, err := fileutils.IsFileExists(filepath.Join(tmpDir, path), true) + assert.NoError(t, err) + assert.False(t, result) + } + // Delete the temporary dir. + createTempDirCallback() + // Restore workspace. + clientTestUtils.ChangeDirAndAssert(t, wd) + } +} + func TestGoVcsFallback(t *testing.T) { _, cleanUpFunc := initGoTest(t) defer cleanUpFunc() diff --git a/testdata/filespecs/go_publish_repo_excludes.json b/testdata/filespecs/go_publish_repo_excludes.json new file mode 100644 index 000000000..979476285 --- /dev/null +++ b/testdata/filespecs/go_publish_repo_excludes.json @@ -0,0 +1,7 @@ +{ + "files": [ + { + "pattern": "${GO_REPO}/*" + } + ] +} \ No newline at end of file diff --git a/testdata/go/project3/.jfrog/projects/go.yaml b/testdata/go/project3/.jfrog/projects/go.yaml new file mode 100644 index 000000000..95ed0eca1 --- /dev/null +++ b/testdata/go/project3/.jfrog/projects/go.yaml @@ -0,0 +1,9 @@ +version: 1 +type: go + +resolver: + repo: ${GO_VIRTUAL_REPO} + serverID: default +deployer: + repo: ${GO_REPO} + serverID: default diff --git a/testdata/go/project3/createGoProject_go.mod_suffix b/testdata/go/project3/createGoProject_go.mod_suffix new file mode 100644 index 000000000..744893775 --- /dev/null +++ b/testdata/go/project3/createGoProject_go.mod_suffix @@ -0,0 +1,8 @@ +module github.com/jfrog/dependency + +require ( + github.com/pkg/errors v0.8.0 + rsc.io/quote v1.5.2 +) + +go 1.13 diff --git a/testdata/go/project3/dependency.go b/testdata/go/project3/dependency.go new file mode 100644 index 000000000..fb1446f05 --- /dev/null +++ b/testdata/go/project3/dependency.go @@ -0,0 +1,11 @@ +package dependency + +import ( + "fmt" + "github.com/pkg/errors" +) + +func PrintHello() error { + fmt.Println("Hello") + return errors.New("abc") +} diff --git a/testdata/go/project3/go.sum b/testdata/go/project3/go.sum new file mode 100644 index 000000000..6dd596a45 --- /dev/null +++ b/testdata/go/project3/go.sum @@ -0,0 +1,7 @@ +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/testdata/go/project4/.jfrog/projects/go.yaml b/testdata/go/project4/.jfrog/projects/go.yaml new file mode 100644 index 000000000..95ed0eca1 --- /dev/null +++ b/testdata/go/project4/.jfrog/projects/go.yaml @@ -0,0 +1,9 @@ +version: 1 +type: go + +resolver: + repo: ${GO_VIRTUAL_REPO} + serverID: default +deployer: + repo: ${GO_REPO} + serverID: default diff --git a/testdata/go/project4/createGoProject_go.mod_suffix b/testdata/go/project4/createGoProject_go.mod_suffix new file mode 100644 index 000000000..744893775 --- /dev/null +++ b/testdata/go/project4/createGoProject_go.mod_suffix @@ -0,0 +1,8 @@ +module github.com/jfrog/dependency + +require ( + github.com/pkg/errors v0.8.0 + rsc.io/quote v1.5.2 +) + +go 1.13 diff --git a/testdata/go/project4/dependency.go b/testdata/go/project4/dependency.go new file mode 100644 index 000000000..1ae8343f3 --- /dev/null +++ b/testdata/go/project4/dependency.go @@ -0,0 +1,11 @@ +package dependency + +import ( + "fmt" + "github.com/pkg/errors" +) + +func PrintHello() error { + fmt.Println("Hello World") + return errors.New("abc") +} diff --git a/testdata/go/project4/dir1/a.txt b/testdata/go/project4/dir1/a.txt new file mode 100644 index 000000000..8d14cbf98 --- /dev/null +++ b/testdata/go/project4/dir1/a.txt @@ -0,0 +1 @@ +a.txt \ No newline at end of file diff --git a/testdata/go/project4/dir1/dir2/b.txt b/testdata/go/project4/dir1/dir2/b.txt new file mode 100644 index 000000000..19acdd81a --- /dev/null +++ b/testdata/go/project4/dir1/dir2/b.txt @@ -0,0 +1 @@ +b.txt \ No newline at end of file diff --git a/testdata/go/project4/dir1/dir2/dir3/c.txt b/testdata/go/project4/dir1/dir2/dir3/c.txt new file mode 100644 index 000000000..f632129c1 --- /dev/null +++ b/testdata/go/project4/dir1/dir2/dir3/c.txt @@ -0,0 +1 @@ +c.txt \ No newline at end of file diff --git a/testdata/go/project4/dir4/d.txt b/testdata/go/project4/dir4/d.txt new file mode 100644 index 000000000..a751d6246 --- /dev/null +++ b/testdata/go/project4/dir4/d.txt @@ -0,0 +1 @@ +d.txt \ No newline at end of file diff --git a/testdata/go/project4/go.sum b/testdata/go/project4/go.sum new file mode 100644 index 000000000..6dd596a45 --- /dev/null +++ b/testdata/go/project4/go.sum @@ -0,0 +1,7 @@ +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/utils/cliutils/commandsflags.go b/utils/cliutils/commandsflags.go index 080fea61f..5c77f30eb 100644 --- a/utils/cliutils/commandsflags.go +++ b/utils/cliutils/commandsflags.go @@ -270,6 +270,9 @@ const ( propsProps = propertiesPrefix + props propsExcludeProps = propertiesPrefix + excludeProps + // Unique go publish flags + goPublishExclusions = GoPublish + exclusions + // Unique build-publish flags buildPublishPrefix = "bp-" bpDryRun = buildPublishPrefix + dryRun @@ -1407,6 +1410,10 @@ var flagsMap = map[string]cli.Flag{ Name: Go, Usage: "[Default: false] Set to true to request audit for a Go project.` `", }, + goPublishExclusions: cli.StringFlag{ + Name: exclusions, + Usage: "[Optional] Semicolon-separated list of exclusions. Exclusions can include the * and the ? wildcards.` `", + }, rescan: cli.BoolFlag{ Name: rescan, Usage: "[Default: false] Set to true when scanning an already successfully scanned build, for example after adding an ignore rule.` `", @@ -1768,7 +1775,7 @@ var commandFlags = map[string][]string{ global, serverIdResolve, serverIdDeploy, repoResolve, repoDeploy, }, GoPublish: { - url, user, password, accessToken, buildName, buildNumber, module, project, detailedSummary, + url, user, password, accessToken, buildName, buildNumber, module, project, detailedSummary, goPublishExclusions, }, Go: { buildName, buildNumber, module, project, noFallback, diff --git a/utils/tests/consts.go b/utils/tests/consts.go index a4c52191c..8373be6d7 100644 --- a/utils/tests/consts.go +++ b/utils/tests/consts.go @@ -94,6 +94,7 @@ const ( SearchAllProdRepo = "search_all_prod_repo.json" SearchDistRepoByInSuffix = "search_dist_repo_by_in_suffix.json" SearchRepo1ByInSuffix = "search_repo1_by_in_suffix.json" + GoPublishRepoExcludes = "go_publish_repo_excludes.json" SearchRepo1IncludeDirs = "search_repo1_include_dirs.json" SearchRepo1NonExistFile = "search_repo1_ant_test_file.json" SearchRepo1NonExistFileAntExclusions = "search_repo1_ant_and_exclusions_test_file.json" @@ -215,6 +216,7 @@ var ( LcRbName1 = "cli-lc-rb1" LcRbName2 = "cli-lc-rb2" LcRbName3 = "cli-lc-rb3" + GoPublishWithExclusionPath = "github.com/jfrog/dependency/@v/github.com/jfrog/dependency@v1.1.1/" // Users UserName1 = "alice" @@ -262,6 +264,16 @@ func GetExpectedExcludeUploadPart2() []string { RtRepo1 + "/", } } +func GetExpectedExcludeUpload2() []string { + return []string{ + RtRepo1 + "/b3.in", + RtRepo1 + "/a2.in", + RtRepo1 + "/a3.in", + RtRepo1 + "/a1.in", + RtRepo1 + "/c", + RtRepo1 + "/", + } +} func GetExpectedExcludeUploadIncludeDir() []string { return []string{ RtRepo1 + "/a2.in", @@ -272,6 +284,14 @@ func GetExpectedExcludeUploadIncludeDir() []string { } } +func GetUploadLegacyPropsExpected() []string { + return []string{ + RtRepo1 + "/data/a1.in", + RtRepo1 + "/data/a2.in", + RtRepo1 + "/data/a3.in", + } +} + func GetSearchAppendedBuildNoPatternExpected() []string { return []string{ RtRepo1 + "/data/a1.in", @@ -2078,3 +2098,54 @@ func GetExpectedLifecycleArtifacts() []string { RtProdRepo + "/c3.in", } } + +func GetGoPublishWithExclusionsExpectedRepoGo() []string { + var expected = []string{ + GoRepo + "/github.com/jfrog/dependency/@v/v1.1.1.info", + GoRepo + "/github.com/jfrog/dependency/@v/v1.1.1.mod", + GoRepo + "/github.com/jfrog/dependency/@v/v1.1.1.zip", + } + return expected +} + +func GetGoPublishWithExclusionsExpectedFiles1() []string { + var expected = []string{ + GoPublishWithExclusionPath + "dir4/d.txt", + } + return expected +} + +func GetGoPublishWithExclusionsExcludedFiles1() []string { + var excluded = []string{ + GoPublishWithExclusionPath + "dir1/a.txt", + GoPublishWithExclusionPath + "dir1/dir2/b.txt", + GoPublishWithExclusionPath + "dir1/dir2/dir3/c.txt", + } + return excluded +} + +func GetGoPublishWithExclusionsExpectedFiles2() []string { + var expected = []string{ + GoPublishWithExclusionPath + "dir4/d.txt", + GoPublishWithExclusionPath + "dir1/a.txt", + } + return expected +} + +func GetGoPublishWithExclusionsExcludedFiles2() []string { + var excluded = []string{ + GoPublishWithExclusionPath + "dir1/dir2/b.txt", + GoPublishWithExclusionPath + "dir1/dir2/dir3/c.txt", + } + return excluded +} + +func GetGoPublishWithExclusionsExcludedFiles3() []string { + var excluded = []string{ + GoPublishWithExclusionPath + "dir1/a.txt", + GoPublishWithExclusionPath + "dir1/dir2/b.txt", + GoPublishWithExclusionPath + "dir1/dir2/dir3/c.txt", + GoPublishWithExclusionPath + "dir4/d.txt", + } + return excluded +} diff --git a/xray_test.go b/xray_test.go index c55d46b76..89527d1c2 100644 --- a/xray_test.go +++ b/xray_test.go @@ -293,7 +293,7 @@ func TestXrayAuditNoTech(t *testing.T) { defer clientTestUtils.ChangeDirAndAssert(t, prevWd) // Run audit on empty folder, expect an error err := xrayCli.Exec("audit") - assert.EqualError(t, err, "could not determine the package manager / build tool used by this project.") + assert.NoError(t, err) } func TestXrayAuditDetectTech(t *testing.T) { From 7e6b04f73d5a59e880a84f4bb67fc5954cfd6314 Mon Sep 17 00:00:00 2001 From: Omer Zidkoni <50792403+omerzi@users.noreply.github.com> Date: Wed, 19 Jul 2023 19:22:38 +0300 Subject: [PATCH 25/25] Promoted version to 2.44.0 (#2082) --- build/npm/v2-jf/package-lock.json | 2 +- build/npm/v2-jf/package.json | 2 +- build/npm/v2/package-lock.json | 2 +- build/npm/v2/package.json | 2 +- go.mod | 8 ++++---- go.sum | 8 ++++---- utils/cliutils/cli_consts.go | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/build/npm/v2-jf/package-lock.json b/build/npm/v2-jf/package-lock.json index c0b4385bc..738e730cd 100644 --- a/build/npm/v2-jf/package-lock.json +++ b/build/npm/v2-jf/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.43.1", + "version": "2.44.0", "lockfileVersion": 1 } diff --git a/build/npm/v2-jf/package.json b/build/npm/v2-jf/package.json index 9a29ffc90..9d43c22dc 100644 --- a/build/npm/v2-jf/package.json +++ b/build/npm/v2-jf/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2-jf", - "version": "2.43.1", + "version": "2.44.0", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/build/npm/v2/package-lock.json b/build/npm/v2/package-lock.json index 66de95f85..d3e36fd1a 100644 --- a/build/npm/v2/package-lock.json +++ b/build/npm/v2/package-lock.json @@ -1,5 +1,5 @@ { "name": "jfrog-cli-v2", - "version": "2.43.1", + "version": "2.44.0", "lockfileVersion": 1 } diff --git a/build/npm/v2/package.json b/build/npm/v2/package.json index cfaa4c69b..0ca1a13ed 100644 --- a/build/npm/v2/package.json +++ b/build/npm/v2/package.json @@ -1,6 +1,6 @@ { "name": "jfrog-cli-v2", - "version": "2.43.1", + "version": "2.44.0", "description": "🐸 Command-line interface for JFrog Artifactory, Xray, Distribution, Pipelines and Mission Control 🐸", "homepage": "https://github.com/jfrog/jfrog-cli", "preferGlobal": true, diff --git a/go.mod b/go.mod index a31b5d245..8567954b4 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,8 @@ require ( github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d github.com/jfrog/build-info-go v1.9.6 github.com/jfrog/gofrog v1.3.0 - github.com/jfrog/jfrog-cli-core/v2 v2.38.0 - github.com/jfrog/jfrog-client-go v1.31.1 + github.com/jfrog/jfrog-cli-core/v2 v2.39.2 + github.com/jfrog/jfrog-client-go v1.31.2 github.com/jszwec/csvutil v1.8.0 github.com/mholt/archiver/v3 v3.5.1 github.com/pkg/errors v0.9.1 @@ -123,8 +123,8 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230717092920-cd976eb1e5c3 +//replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 dev // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.2.6-0.20230418122323-2bf299dd6d27 -replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230717090738-b2e0c7bcc026 +//replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20230717090738-b2e0c7bcc026 diff --git a/go.sum b/go.sum index a9953b121..0dc8a1067 100644 --- a/go.sum +++ b/go.sum @@ -238,10 +238,10 @@ github.com/jfrog/build-info-go v1.9.6 h1:lCJ2j5uXAlJsSwDe5J8WD7Co1f/hUlZvMfwfb5A github.com/jfrog/build-info-go v1.9.6/go.mod h1:GbuFS+viHCKZYx9nWHYu7ab1DgQkFdtVN3BJPUNb2D4= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230717092920-cd976eb1e5c3 h1:ED7QzMz/KA/7ps2bNvRiWbqBP/BbExWlUrJWcAoGiHM= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230717092920-cd976eb1e5c3/go.mod h1:QjTOL5xFgplonx47OnXXXurRtpQGDquGmrTbpe011EY= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230717090738-b2e0c7bcc026 h1:Xam/SD9ZqanqexbX2iW2H1fH5MLB9qx6vN8SK8wBMhA= -github.com/jfrog/jfrog-client-go v1.28.1-0.20230717090738-b2e0c7bcc026/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= +github.com/jfrog/jfrog-cli-core/v2 v2.39.2 h1:T0h+acOkaRqwrZyzizzL7lO+Yo2KpGcAypITHxKWSEI= +github.com/jfrog/jfrog-cli-core/v2 v2.39.2/go.mod h1:/HJ9mO3AZsACtQWxkwMj7REWPdXT3yHKjJXjPHlmB34= +github.com/jfrog/jfrog-client-go v1.31.2 h1:foy8owM2lS8jZL7zuBPtcx1RpF1GeIXaXF8hIufyr4I= +github.com/jfrog/jfrog-client-go v1.31.2/go.mod h1:qEJxoe68sUtqHJ1YhXv/7pKYP/9p1D5tJrruzJKYeoI= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jszwec/csvutil v1.8.0 h1:G7vS2LGdpZZDH1HmHeNbxOaJ/ZnJlpwGFvOkTkJzzNk= diff --git a/utils/cliutils/cli_consts.go b/utils/cliutils/cli_consts.go index b0f699b5b..f73b0e643 100644 --- a/utils/cliutils/cli_consts.go +++ b/utils/cliutils/cli_consts.go @@ -4,7 +4,7 @@ import "time" const ( // General CLI constants - CliVersion = "2.43.1" + CliVersion = "2.44.0" ClientAgent = "jfrog-cli-go" // CLI base commands constants: