Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,8 @@ It is also possible to set the latest JFrog CLI version by adding the _version_
version: latest
```

With `download-repository`, prefer a concrete `version: X.Y.Z` over `latest`. See [Downloading JFrog CLI from Artifactory](#downloading-jfrog-cli-from-artifactory).

| Important: Only JFrog CLI versions 1.46.4 or above are supported. |
|-------------------------------------------------------------------|

Expand Down Expand Up @@ -417,10 +419,17 @@ In this example, each job builds and publishes a different service from the mono

If your agent has no Internet access, you can configure the workflow to download JFrog CLI from a [remote repository](https://www.jfrog.com/confluence/display/JFROG/Remote+Repositories) in your JFrog Artifactory, which is configured to proxy the official download URL.

> [!NOTE]
> With `download-repository`, prefer a concrete `version: X.Y.Z` over `latest`.
>
> `latest` is not resolved to a version number. It becomes the literal path segment `[RELEASE]` in the download URL (`v2/[RELEASE]/jfrog-cli-.../jfrog`), and a generic repository serves that path like any other. If the repository has **Store Artifacts Locally** enabled (the default), the binary returned for that path is cached under it, so later runs can keep receiving that same binary instead of a newer CLI. A concrete version avoids this, because every version has its own immutable path.
>
> Jobs that can reach the internet and want the newest CLI: omit `download-repository`.

Here's how you do this:

1. Create a remote repository in Artifactory. Name the repository jfrog-cli-remote and set its URL to https://releases.jfrog.io/artifactory/jfrog-cli/
2. Set _download-repository_ input to jfrog-cli-remote:
2. Set _download-repository_ input to jfrog-cli-remote and pin `version`:

```yml
- uses: step-security/setup-jfrog-cli@v5
Expand All @@ -430,6 +439,7 @@ Here's how you do this:
JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }}

with:
version: X.Y.Z
download-repository: jfrog-cli-remote
```
</details>
Expand Down
6 changes: 3 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ description: "Install and configure JFrog CLI."
author: "step-security"
inputs:
version:
description: "JFrog CLI Version"
default: "2.91.0"
description: "JFrog CLI Version. A concrete X.Y.Z is recommended when download-repository points to a remote repository that stores artifacts locally, since latest is requested as the v2/[RELEASE] path and can be served from cache."
default: "2.124.0"
required: false
download-repository:
description: "Remote repository in Artifactory pointing to 'https://releases.jfrog.io/artifactory/jfrog-cli'. Use this parameter in case you don't have an Internet access."
description: "Remote repository in Artifactory pointing to 'https://releases.jfrog.io/artifactory/jfrog-cli'. Use this parameter in case you don't have an Internet access. When the repository stores artifacts locally, prefer a concrete version over latest: latest is requested as the literal v2/[RELEASE] path, and the binary cached under that path can keep being served on later runs."
required: false
oidc-provider-name:
description: "Provider Name's value that was set in OpenId Connect integration in the JFrog platform."
Expand Down
15 changes: 14 additions & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,8 @@ class Utils {
static LATEST_CLI_VERSION = 'latest';
// The value in the download URL to set to get the latest version
static LATEST_RELEASE_VERSION = '[RELEASE]';
// Logged when version=latest is downloaded through a remote repository, which caches the literal [RELEASE] path
static LATEST_FROM_REMOTE_INFO = 'download-repository is set with version=latest, so the CLI is requested from the literal path v2/[RELEASE] instead of a version number. If that repository stores artifacts locally, the binary cached under this path can keep being served on later runs. Use a concrete version to download from a per-version path, or omit download-repository if the runner can reach releases.jfrog.io.';
// Placeholder CLI version to use to keep 'latest' in cache.
static LATEST_SEMVER = '100.100.100';
// The default server id name for separate env config
Expand Down Expand Up @@ -869,6 +871,7 @@ class Utils {
let version = core.getInput(Utils.CLI_VERSION_ARG);
let cliRemote = core.getInput(Utils.CLI_REMOTE_ARG);
const isLatestVer = version === Utils.LATEST_CLI_VERSION;
Utils.logIfLatestDownloadedFromRemote(version, cliRemote);
if (!isLatestVer && (0, semver_1.lt)(version, this.MIN_CLI_VERSION)) {
throw new Error('Requested to download JFrog CLI version ' + version + ' but must be at least ' + this.MIN_CLI_VERSION);
}
Expand Down Expand Up @@ -952,6 +955,16 @@ class Utils {
}
return `${artifactoryUrl}/${downloadDetails.repository}/v${major}/${version}/${architecture}/${fileName}`;
}
/**
* Log when latest is resolved through an Artifactory repository.
* [RELEASE] is part of the artifact path, so a remote repository caches it like any other file
* and keeps serving the first version it resolved. Pin a concrete version instead.
*/
static logIfLatestDownloadedFromRemote(version, cliRemote) {
if (cliRemote && version === Utils.LATEST_CLI_VERSION) {
core.info(Utils.LATEST_FROM_REMOTE_INFO);
}
}
// Get Config Tokens created on your local machine using JFrog CLI.
// The Tokens configured with JF_ENV_ environment variables.
static getConfigTokens() {
Expand Down Expand Up @@ -58445,7 +58458,7 @@ module.exports = /*#__PURE__*/JSON.parse('{"application/1d-interleaved-parityfec
/***/ ((module) => {

"use strict";
module.exports = {"rE":"5.1.0"};
module.exports = {"rE":"5.2.0"};

/***/ })

Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

21 changes: 18 additions & 3 deletions dist/post/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.checkConnectionToArtifactory = checkConnectionToArtifactory;
const core = __importStar(__nccwpck_require__(7484));
const fs_1 = __nccwpck_require__(9896);
const path_1 = __nccwpck_require__(6928);
const utils_1 = __nccwpck_require__(9277);
const job_summary_1 = __nccwpck_require__(1298);
const evidence_collection_1 = __nccwpck_require__(1180);
Expand Down Expand Up @@ -128,8 +130,8 @@ async function collectAndPublishBuildInfoIfNeeded() {
// We allow this step to fail, and we don't want to fail the entire build publish if they do.
try {
core.startGroup('Collect the Git information');
const gitDir = (__nccwpck_require__(6928).join)(workingDirectory, '.git');
if ((__nccwpck_require__(9896).existsSync)(gitDir)) {
const gitDir = (0, path_1.join)(workingDirectory, '.git');
if ((0, fs_1.existsSync)(gitDir)) {
await utils_1.Utils.runCli(['rt', 'build-add-git'], { cwd: workingDirectory });
}
else {
Expand Down Expand Up @@ -1121,6 +1123,8 @@ class Utils {
static LATEST_CLI_VERSION = 'latest';
// The value in the download URL to set to get the latest version
static LATEST_RELEASE_VERSION = '[RELEASE]';
// Logged when version=latest is downloaded through a remote repository, which caches the literal [RELEASE] path
static LATEST_FROM_REMOTE_INFO = 'download-repository is set with version=latest, so the CLI is requested from the literal path v2/[RELEASE] instead of a version number. If that repository stores artifacts locally, the binary cached under this path can keep being served on later runs. Use a concrete version to download from a per-version path, or omit download-repository if the runner can reach releases.jfrog.io.';
// Placeholder CLI version to use to keep 'latest' in cache.
static LATEST_SEMVER = '100.100.100';
// The default server id name for separate env config
Expand Down Expand Up @@ -1191,6 +1195,7 @@ class Utils {
let version = core.getInput(Utils.CLI_VERSION_ARG);
let cliRemote = core.getInput(Utils.CLI_REMOTE_ARG);
const isLatestVer = version === Utils.LATEST_CLI_VERSION;
Utils.logIfLatestDownloadedFromRemote(version, cliRemote);
if (!isLatestVer && (0, semver_1.lt)(version, this.MIN_CLI_VERSION)) {
throw new Error('Requested to download JFrog CLI version ' + version + ' but must be at least ' + this.MIN_CLI_VERSION);
}
Expand Down Expand Up @@ -1274,6 +1279,16 @@ class Utils {
}
return `${artifactoryUrl}/${downloadDetails.repository}/v${major}/${version}/${architecture}/${fileName}`;
}
/**
* Log when latest is resolved through an Artifactory repository.
* [RELEASE] is part of the artifact path, so a remote repository caches it like any other file
* and keeps serving the first version it resolved. Pin a concrete version instead.
*/
static logIfLatestDownloadedFromRemote(version, cliRemote) {
if (cliRemote && version === Utils.LATEST_CLI_VERSION) {
core.info(Utils.LATEST_FROM_REMOTE_INFO);
}
}
// Get Config Tokens created on your local machine using JFrog CLI.
// The Tokens configured with JF_ENV_ environment variables.
static getConfigTokens() {
Expand Down Expand Up @@ -47716,7 +47731,7 @@ legacyRestEndpointMethods.VERSION = VERSION;
/***/ ((module) => {

"use strict";
module.exports = {"rE":"5.1.0"};
module.exports = {"rE":"5.2.0"};

/***/ })

Expand Down
2 changes: 1 addition & 1 deletion dist/post/index.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@step-security/setup-jfrog-cli",
"version": "5.1.0",
"version": "5.2.0",
"private": true,
"description": "Setup JFrog CLI in GitHub Actions",
"main": "dist/index.js",
Expand Down
6 changes: 4 additions & 2 deletions src/cleanup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as core from '@actions/core';
import { existsSync } from 'fs';
import { join } from 'path';
import { Utils } from './utils';
import { JobSummary } from './job-summary';
import { collectEvidences } from './evidence-collection';
Expand Down Expand Up @@ -105,8 +107,8 @@ async function collectAndPublishBuildInfoIfNeeded() {
// We allow this step to fail, and we don't want to fail the entire build publish if they do.
try {
core.startGroup('Collect the Git information');
const gitDir: string = require('path').join(workingDirectory, '.git');
if (require('fs').existsSync(gitDir)) {
const gitDir: string = join(workingDirectory, '.git');
if (existsSync(gitDir)) {
await Utils.runCli(['rt', 'build-add-git'], { cwd: workingDirectory });
} else {
core.info('No .git directory found. Skipping Git information collection.');
Expand Down
1 change: 0 additions & 1 deletion src/evidence-collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as core from '@actions/core';
import { Utils } from './utils';
import { HttpClient, HttpClientResponse } from '@actions/http-client';
import { OutgoingHttpHeaders } from 'http';
import { JfrogCredentials } from './types';
import { promises as fs } from 'fs';
import * as path from 'path';

Expand Down
3 changes: 0 additions & 3 deletions src/job-summary.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import * as core from '@actions/core';
import { gte } from 'semver';
import { Octokit } from '@octokit/core';
import { OctokitResponse } from '@octokit/types/dist-types/OctokitResponse';
import * as github from '@actions/github';
import { promisify } from 'util';
import { gzip } from 'zlib';
import path from 'path';
import { existsSync, promises as fs } from 'fs';
import { HttpClient, HttpClientResponse } from '@actions/http-client';
import { OutgoingHttpHeaders } from 'http';
import { tmpdir } from 'os';
import { Utils } from './utils';

Expand Down
15 changes: 15 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export class Utils {
public static readonly LATEST_CLI_VERSION: string = 'latest';
// The value in the download URL to set to get the latest version
private static readonly LATEST_RELEASE_VERSION: string = '[RELEASE]';
// Logged when version=latest is downloaded through a remote repository, which caches the literal [RELEASE] path
public static readonly LATEST_FROM_REMOTE_INFO: string =
'download-repository is set with version=latest, so the CLI is requested from the literal path v2/[RELEASE] instead of a version number. If that repository stores artifacts locally, the binary cached under this path can keep being served on later runs. Use a concrete version to download from a per-version path, or omit download-repository if the runner can reach releases.jfrog.io.';
// Placeholder CLI version to use to keep 'latest' in cache.
public static readonly LATEST_SEMVER: string = '100.100.100';
// The default server id name for separate env config
Expand Down Expand Up @@ -108,6 +111,7 @@ export class Utils {
let version: string = core.getInput(Utils.CLI_VERSION_ARG);
let cliRemote: string = core.getInput(Utils.CLI_REMOTE_ARG);
const isLatestVer: boolean = version === Utils.LATEST_CLI_VERSION;
Utils.logIfLatestDownloadedFromRemote(version, cliRemote);

if (!isLatestVer && lt(version, this.MIN_CLI_VERSION)) {
throw new Error('Requested to download JFrog CLI version ' + version + ' but must be at least ' + this.MIN_CLI_VERSION);
Expand Down Expand Up @@ -199,6 +203,17 @@ export class Utils {
return `${artifactoryUrl}/${downloadDetails.repository}/v${major}/${version}/${architecture}/${fileName}`;
}

/**
* Log when latest is resolved through an Artifactory repository.
* [RELEASE] is part of the artifact path, so a remote repository caches it like any other file
* and keeps serving the first version it resolved. Pin a concrete version instead.
*/
public static logIfLatestDownloadedFromRemote(version: string, cliRemote: string): void {
if (cliRemote && version === Utils.LATEST_CLI_VERSION) {
core.info(Utils.LATEST_FROM_REMOTE_INFO);
}
}

// Get Config Tokens created on your local machine using JFrog CLI.
// The Tokens configured with JF_ENV_ environment variables.
public static getConfigTokens(): Set<string> {
Expand Down
Loading
Loading