Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 'jf' path on cleanup and validate JobSummary supported CLI version #201

Merged
merged 43 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
1f707ff
Fix path
sverdlov93 Sep 2, 2024
36f0d5f
Update to version 4.3.2
sverdlov93 Sep 2, 2024
14b297c
Merge branch 'master' of https://github.com/jfrog/setup-jfrog-cli int…
sverdlov93 Sep 2, 2024
6c9b253
Merge branch 'master' of https://github.com/jfrog/setup-jfrog-cli int…
sverdlov93 Sep 3, 2024
3fa8574
Update to version 4.3.3
sverdlov93 Sep 3, 2024
6aac057
Update to version 4.3.3
sverdlov93 Sep 3, 2024
a8d9909
Update to version 4.3.3
sverdlov93 Sep 3, 2024
45dac24
Update to version 4.3.3
sverdlov93 Sep 3, 2024
bb23156
Update to version 4.3.3
sverdlov93 Sep 3, 2024
c467e4c
Update to version 4.3.3
sverdlov93 Sep 3, 2024
bed193c
Update to version 4.3.3
sverdlov93 Sep 3, 2024
33a0a39
Merge branch 'master' of https://github.com/jfrog/setup-jfrog-cli int…
sverdlov93 Sep 3, 2024
ea46492
Update to version 4.3.3
sverdlov93 Sep 3, 2024
88050b2
Update to version 4.3.3
sverdlov93 Sep 3, 2024
b0c45da
Update to version 4.3.3
sverdlov93 Sep 3, 2024
934010e
Update to version 4.3.3
sverdlov93 Sep 3, 2024
b1d2157
Update to version 4.3.3
sverdlov93 Sep 3, 2024
46ee824
Update to version 4.3.3
sverdlov93 Sep 3, 2024
d1a97b2
Update to version 4.3.3
sverdlov93 Sep 3, 2024
2133948
Update to version 4.3.3
sverdlov93 Sep 3, 2024
341ffc5
Update to version 4.3.3
sverdlov93 Sep 3, 2024
cf48d6a
Update to version 4.3.3
sverdlov93 Sep 3, 2024
bc223d9
Update to version 4.3.3
sverdlov93 Sep 3, 2024
7ba7bde
Update to version 4.3.3
sverdlov93 Sep 3, 2024
a7998c5
Update to version 4.3.3
sverdlov93 Sep 3, 2024
f38bc5a
Update to version 4.3.3
sverdlov93 Sep 3, 2024
066a7e8
Update to version 4.3.3
sverdlov93 Sep 4, 2024
e71b848
Update to version 4.3.3
sverdlov93 Sep 4, 2024
c8fa253
Update to version 4.3.3
sverdlov93 Sep 4, 2024
2738861
Update to version 4.3.3
sverdlov93 Sep 4, 2024
94b8539
Update to version 4.3.3
sverdlov93 Sep 4, 2024
36b9d45
Update to version 4.3.3
sverdlov93 Sep 4, 2024
a197588
Update to version 4.3.3
sverdlov93 Sep 4, 2024
107905e
Update to version 4.3.3
sverdlov93 Sep 4, 2024
1dc2982
Update to version 4.3.
sverdlov93 Sep 4, 2024
dc9e306
Update to version 4.3.
sverdlov93 Sep 4, 2024
0d66af4
Update to version 4.3.
sverdlov93 Sep 4, 2024
171557c
Update to version 4.3.
sverdlov93 Sep 4, 2024
f1087f2
Update .github/workflows/auto-build-publish-test.yml
sverdlov93 Sep 4, 2024
e7517c9
Update src/cleanup.ts
RobiNino Sep 4, 2024
769af07
Update src/utils.ts
RobiNino Sep 4, 2024
4a7729b
CR comments
RobiNino Sep 4, 2024
a29a2bd
CR comments
RobiNino Sep 4, 2024
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
4 changes: 4 additions & 0 deletions .github/workflows/auto-build-publish-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ concurrency:

jobs:
Auto-Build-Publish-Test:
name: Auto-Build-Publish-Test (${{ matrix.os }}) - (CLI ${{ matrix.cli-version }})
if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push'
strategy:
fail-fast: false
matrix:
os: [ ubuntu, windows, macos ]
cli-version: [ "latest", "2.66.0" ]
sverdlov93 marked this conversation as resolved.
Show resolved Hide resolved
runs-on: ${{ matrix.os }}-latest
steps:
- name: Checkout Repository
Expand Down Expand Up @@ -51,6 +53,8 @@ jobs:
- name: Setup JFrog CLI
id: setup-jfrog-cli
uses: ./
with:
version: ${{ matrix.cli-version }}
env:
JF_URL: http://localhost:8081/
JF_USER: admin
Expand Down
129 changes: 90 additions & 39 deletions lib/cleanup.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,12 @@ const core = __importStar(require("@actions/core"));
const utils_1 = require("./utils");
function cleanup() {
return __awaiter(this, void 0, void 0, function* () {
if (!addCachedJfToPath()) {
core.error('Could not find JFrog CLI path in the step state. Skipping cleanup.');
if (!utils_1.Utils.loadFromCache(core.getInput(utils_1.Utils.CLI_VERSION_ARG))) {
core.warning('Could not find JFrog CLI executable. Skipping cleanup.');
return;
}
// Auto-publish build info if needed
try {
if (!core.getBooleanInput(utils_1.Utils.AUTO_BUILD_PUBLISH_DISABLE)) {
yield collectAndPublishBuildInfoIfNeeded();
}
}
catch (error) {
core.warning('failed while attempting to publish build info: ' + error);
}
// Generate job summary
try {
if (!core.getBooleanInput(utils_1.Utils.JOB_SUMMARY_DISABLE)) {
core.startGroup('Generating Job Summary');
yield utils_1.Utils.runCli(['generate-summary-markdown']);
yield utils_1.Utils.setMarkdownAsJobSummary();
core.endGroup();
}
}
catch (error) {
core.warning('failed while attempting to generate job summary: ' + error);
}
// Run post tasks related to Build Info (auto build publish, job summary)
yield buildInfoPostTasks();
// Cleanup JFrog CLI servers configuration
try {
core.startGroup('Cleanup JFrog CLI servers configuration');
Expand All @@ -74,36 +55,65 @@ function cleanup() {
}
});
}
function addCachedJfToPath() {
// Get the JFrog CLI path from step state. saveState/getState are methods to pass data between a step, and it's cleanup function.
const jfCliPath = core.getState(utils_1.Utils.JF_CLI_PATH_STATE);
if (!jfCliPath) {
// This means that the JFrog CLI was not installed in the first place, because there was a failure in the installation step.
return false;
}
core.addPath(jfCliPath);
return true;
/**
* Executes post tasks related to build information.
*
* This function performs several tasks after the main build process:
* 1. Checks if auto build publish and job summary are disabled.
* 2. Verifies connection to JFrog Artifactory.
* 3. Collects and publishes build information if needed.
* 4. Generates a job summary if required.
*/
function buildInfoPostTasks() {
return __awaiter(this, void 0, void 0, function* () {
const disableAutoBuildPublish = core.getBooleanInput(utils_1.Utils.AUTO_BUILD_PUBLISH_DISABLE);
const disableJobSummary = core.getBooleanInput(utils_1.Utils.JOB_SUMMARY_DISABLE) || !utils_1.Utils.isJobSummarySupported();
if (disableAutoBuildPublish && disableJobSummary) {
core.info(`Both auto-build-publish and job-summary are disabled. Skipping Build Info post tasks.`);
return;
}
// Check connection to Artifactory before proceeding with build info post tasks
if (!(yield checkConnectionToArtifactory())) {
return;
}
// Auto-publish build info if needed
if (!disableAutoBuildPublish) {
yield collectAndPublishBuildInfoIfNeeded();
}
else {
core.info('Auto build info publish is disabled. Skipping auto build info collection and publishing');
}
// Generate job summary if not disabled and the JFrog CLI version supports it
if (!disableJobSummary) {
yield generateJobSummary();
}
else {
core.info('Job summary is disabled. Skipping job summary generation');
}
});
}
function hasUnpublishedModules(workingDirectory) {
return __awaiter(this, void 0, void 0, function* () {
// Save the old value of the environment variable to revert it later
const origValue = process.env[utils_1.Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV];
try {
core.startGroup('Check for unpublished modules');
// Avoid saving a command summary for this dry-run command
core.exportVariable(utils_1.Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV, '');
// Running build-publish command with a dry-run flag to check if there are any unpublished modules, 'silent' to avoid polluting the logs
const responseStr = yield utils_1.Utils.runCliAndGetOutput(['rt', 'build-publish', '--dry-run'], { silent: true, cwd: workingDirectory });
const responseStr = yield utils_1.Utils.runCliAndGetOutput(['rt', 'build-publish', '--dry-run'], { cwd: workingDirectory });
// Parse the JSON string to an object
const response = JSON.parse(responseStr);
// Check if the "modules" key exists and if it's an array with more than one item
return response.modules != undefined && Array.isArray(response.modules) && response.modules.length > 0;
}
catch (error) {
core.error('Failed to parse JSON: ' + error);
return false; // Return false if parsing fails
core.warning('Failed to check if there are any unpublished modules: ' + error);
return false;
}
finally {
core.exportVariable(utils_1.Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV, origValue);
core.endGroup();
}
});
}
Expand All @@ -121,14 +131,19 @@ function collectAndPublishBuildInfoIfNeeded() {
yield utils_1.Utils.runCli(['rt', 'build-add-git'], { cwd: workingDirectory });
}
catch (error) {
core.warning('failed while attempting to collect Git information: ' + error);
core.warning('Failed while attempting to collect Git information: ' + error);
}
finally {
core.endGroup();
}
// Publish the build info to Artifactory
try {
core.startGroup('Publish the build info to JFrog Artifactory');
yield utils_1.Utils.runCli(['rt', 'build-publish'], { cwd: workingDirectory });
}
finally {
core.endGroup();
}
core.startGroup('Publish the build info to JFrog Artifactory');
yield utils_1.Utils.runCli(['rt', 'build-publish'], { cwd: workingDirectory });
core.endGroup();
});
}
function getWorkingDirectory() {
Expand All @@ -138,4 +153,40 @@ function getWorkingDirectory() {
}
return workingDirectory;
}
function checkConnectionToArtifactory() {
return __awaiter(this, void 0, void 0, function* () {
try {
core.startGroup('Checking connection to JFrog Artifactory');
const pingResult = yield utils_1.Utils.runCliAndGetOutput(['rt', 'ping']);
if (pingResult !== 'OK') {
core.debug(`Ping result: ${pingResult}`);
core.warning('Could not connect to Artifactory. Skipping Build Info post tasks.');
return false;
}
return true;
}
catch (error) {
core.warning(`An error occurred while trying to connect to Artifactory: ${error}. Skipping Build Info post tasks.`);
return false;
}
finally {
core.endGroup();
}
});
}
function generateJobSummary() {
return __awaiter(this, void 0, void 0, function* () {
try {
core.startGroup('Generating Job Summary');
yield utils_1.Utils.runCli(['generate-summary-markdown']);
yield utils_1.Utils.setMarkdownAsJobSummary();
}
catch (error) {
core.warning('Failed while attempting to generate job summary: ' + error);
}
finally {
core.endGroup();
}
});
}
cleanup();
94 changes: 58 additions & 36 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,48 +200,45 @@ class Utils {
return __awaiter(this, void 0, void 0, function* () {
let version = core.getInput(Utils.CLI_VERSION_ARG);
let cliRemote = core.getInput(Utils.CLI_REMOTE_ARG);
let major = version.split('.')[0];
if (version === Utils.LATEST_CLI_VERSION) {
version = Utils.LATEST_RELEASE_VERSION;
major = '2';
}
else if ((0, semver_1.lt)(version, this.MIN_CLI_VERSION)) {
const isLatestVer = version === Utils.LATEST_CLI_VERSION;
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);
}
let jfFileName = Utils.getJfExecutableName();
let jfrogFileName = Utils.getJFrogExecutableName();
if (this.loadFromCache(jfFileName, jfrogFileName, version)) {
// Download is not needed
if (!isLatestVer && this.loadFromCache(version)) {
core.info('Found JFrog CLI in cache. No need to download');
return;
}
// Download JFrog CLI
let downloadDetails = Utils.extractDownloadDetails(cliRemote, jfrogCredentials);
let url = Utils.getCliUrl(major, version, jfrogFileName, downloadDetails);
let url = Utils.getCliUrl(version, Utils.getJFrogExecutableName(), downloadDetails);
core.info('Downloading JFrog CLI from ' + url);
let downloadedExecutable = yield toolCache.downloadTool(url, undefined, downloadDetails.auth);
// Cache 'jf' and 'jfrog' executables
yield this.cacheAndAddPath(downloadedExecutable, version, jfFileName, jfrogFileName);
yield this.cacheAndAddPath(downloadedExecutable, version);
});
}
/**
* Try to load the JFrog CLI executables from cache.
*
* @param jfFileName - 'jf' or 'jf.exe'
* @param jfrogFileName - 'jfrog' or 'jfrog.exe'
* @param version - JFrog CLI version
* @returns true if the CLI executable was loaded from cache and added to path
*/
static loadFromCache(jfFileName, jfrogFileName, version) {
if (version === Utils.LATEST_RELEASE_VERSION) {
return false;
}
let jfExecDir = toolCache.find(jfFileName, version);
let jfrogExecDir = toolCache.find(jfrogFileName, version);
static loadFromCache(version) {
const jfFileName = Utils.getJfExecutableName();
const jfrogFileName = Utils.getJFrogExecutableName();
if (version === Utils.LATEST_CLI_VERSION) {
// If the version is 'latest', we keep it on cache as 100.100.100
version = Utils.LATEST_SEMVER;
}
const jfExecDir = toolCache.find(jfFileName, version);
const jfrogExecDir = toolCache.find(jfrogFileName, version);
if (jfExecDir && jfrogExecDir) {
core.addPath(jfExecDir);
core.addPath(jfrogExecDir);
// Save the JF CLI path to use on cleanup. saveState/getState are methods to pass data between a step, and its cleanup function.
core.saveState(Utils.JF_CLI_PATH_STATE, jfExecDir);
if (!Utils.isWindows()) {
(0, fs_1.chmodSync)((0, path_1.join)(jfExecDir, jfFileName), 0o555);
(0, fs_1.chmodSync)((0, path_1.join)(jfrogExecDir, jfrogFileName), 0o555);
}
return true;
}
return false;
Expand All @@ -250,11 +247,15 @@ class Utils {
* Add JFrog CLI executables to cache and to the system path.
* @param downloadedExecutable - Path to the downloaded JFrog CLI executable
* @param version - JFrog CLI version
* @param jfFileName - 'jf' or 'jf.exe'
* @param jfrogFileName - 'jfrog' or 'jfrog.exe'
*/
static cacheAndAddPath(downloadedExecutable, version, jfFileName, jfrogFileName) {
static cacheAndAddPath(downloadedExecutable, version) {
return __awaiter(this, void 0, void 0, function* () {
if (version === Utils.LATEST_CLI_VERSION) {
// If the version is 'latest', we keep it on cache as 100.100.100 as GitHub actions cache supports only semver versions
version = Utils.LATEST_SEMVER;
}
const jfFileName = Utils.getJfExecutableName();
const jfrogFileName = Utils.getJFrogExecutableName();
let jfCacheDir = yield toolCache.cacheFile(downloadedExecutable, jfFileName, jfFileName, version);
core.addPath(jfCacheDir);
let jfrogCacheDir = yield toolCache.cacheFile(downloadedExecutable, jfrogFileName, jfrogFileName, version);
Expand All @@ -263,13 +264,25 @@ class Utils {
(0, fs_1.chmodSync)((0, path_1.join)(jfCacheDir, jfFileName), 0o555);
(0, fs_1.chmodSync)((0, path_1.join)(jfrogCacheDir, jfrogFileName), 0o555);
}
// Save the JF CLI path to use on cleanup. saveState/getState are methods to pass data between a step, and it's cleanup function.
core.saveState(Utils.JF_CLI_PATH_STATE, jfCacheDir);
});
}
static getCliUrl(major, version, fileName, downloadDetails) {
let architecture = 'jfrog-cli-' + Utils.getArchitecture();
let artifactoryUrl = downloadDetails.artifactoryUrl.replace(/\/$/, '');
/**
* Get the JFrog CLI download URL.
* @param version - Requested version
* @param fileName - Executable file name
* @param downloadDetails - Source Artifactory details
*/
static getCliUrl(version, fileName, downloadDetails) {
const architecture = 'jfrog-cli-' + Utils.getArchitecture();
const artifactoryUrl = downloadDetails.artifactoryUrl.replace(/\/$/, '');
let major;
if (version === Utils.LATEST_CLI_VERSION) {
version = Utils.LATEST_RELEASE_VERSION;
major = '2';
}
else {
major = version.split('.')[0];
}
return `${artifactoryUrl}/${downloadDetails.repository}/v${major}/${version}/${architecture}/${fileName}`;
}
// Get Config Tokens created on your local machine using JFrog CLI.
Expand Down Expand Up @@ -411,11 +424,14 @@ class Utils {
*/
static runCliAndGetOutput(args, options) {
return __awaiter(this, void 0, void 0, function* () {
let output = yield (0, exec_1.getExecOutput)('jf', args, options);
let output;
output = yield (0, exec_1.getExecOutput)('jf', args, Object.assign(Object.assign({}, options), { ignoreReturnCode: true }));
if (output.exitCode !== core.ExitCode.Success) {
core.info(output.stdout);
core.info(output.stderr);
throw new Error('JFrog CLI exited with exit code ' + output.exitCode);
if (options === null || options === void 0 ? void 0 : options.silent) {
core.info(output.stdout);
core.info(output.stderr);
}
throw new Error(`JFrog CLI exited with exit code ${output.exitCode}`);
}
return output.stdout;
});
Expand Down Expand Up @@ -467,6 +483,10 @@ class Utils {
}
return;
}
static isJobSummarySupported() {
const version = core.getInput(Utils.CLI_VERSION_ARG);
return version === Utils.LATEST_CLI_VERSION || (0, semver_1.gt)(version, Utils.MIN_CLI_VERSION_JOB_SUMMARY);
}
/**
* Generates GitHub workflow unified Summary report.
* This function runs as part of post-workflow cleanup function,
Expand Down Expand Up @@ -621,14 +641,16 @@ Utils.MIN_CLI_VERSION = '1.46.4';
Utils.LATEST_CLI_VERSION = 'latest';
// The value in the download URL to set to get the latest version
Utils.LATEST_RELEASE_VERSION = '[RELEASE]';
// State name for saving JF CLI path to use on cleanup
Utils.JF_CLI_PATH_STATE = 'JF_CLI_PATH_STATE';
// Placeholder CLI version to use to keep 'latest' in cache.
Utils.LATEST_SEMVER = '100.100.100';
// The default server id name for separate env config
Utils.SETUP_JFROG_CLI_SERVER_ID = 'setup-jfrog-cli-server';
// Directory name which holds markdown files for the Workflow summary
Utils.JOB_SUMMARY_DIR_NAME = 'jfrog-command-summary';
// JFrog CLI command summary output directory environment variable
Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV = 'JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR';
// Minimum JFrog CLI version supported for job summary command
Utils.MIN_CLI_VERSION_JOB_SUMMARY = '2.66.0';
// Inputs
// Version input
Utils.CLI_VERSION_ARG = 'version';
Expand Down
2 changes: 1 addition & 1 deletion node_modules/.package-lock.json

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

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": "@jfrog/setup-jfrog-cli",
"version": "4.3.2",
"version": "4.3.3",
"private": true,
"description": "Setup JFrog CLI in GitHub Actions",
"main": "lib/main.js",
Expand Down
Loading
Loading