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

Automatic build-add-git & build-publish on post job run #185

Merged
merged 99 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
99 commits
Select commit Hold shift + click to select a range
9364315
upadte deps
sverdlov93 Aug 12, 2024
24c977b
Mask secrets
sverdlov93 Aug 12, 2024
0b6390f
Mask secrets
sverdlov93 Aug 12, 2024
8497d5f
Mask secrets
sverdlov93 Aug 12, 2024
19f3d3a
Mask secrets
sverdlov93 Aug 12, 2024
8599cf8
Mask secrets
sverdlov93 Aug 12, 2024
8e7611d
Mask secrets
sverdlov93 Aug 12, 2024
6362123
Mask secrets
sverdlov93 Aug 12, 2024
84fbd21
Mask secrets
sverdlov93 Aug 12, 2024
02369af
Mask secrets
sverdlov93 Aug 12, 2024
420be2b
Update readme
sverdlov93 Aug 12, 2024
e88220d
Update readme
sverdlov93 Aug 12, 2024
226e945
Merge branch 'master' of https://github.com/jfrog/setup-jfrog-cli int…
sverdlov93 Aug 12, 2024
8ca771f
Update readme
sverdlov93 Aug 12, 2024
7f78231
Update readme
sverdlov93 Aug 12, 2024
ff2d0f0
Update readme
sverdlov93 Aug 12, 2024
a2f94e9
Update readme
sverdlov93 Aug 12, 2024
fe2792c
Update readme
sverdlov93 Aug 12, 2024
52a6af4
Update readme
sverdlov93 Aug 12, 2024
d14a9ff
Update readme
sverdlov93 Aug 12, 2024
12d75a2
Update readme
sverdlov93 Aug 12, 2024
372eea8
Update readme
sverdlov93 Aug 12, 2024
01e7908
Update readme
sverdlov93 Aug 12, 2024
43e72b2
Update readme
sverdlov93 Aug 13, 2024
84c6821
Merge branch 'master' of https://github.com/jfrog/setup-jfrog-cli int…
sverdlov93 Aug 15, 2024
1e2c2f7
Update readme
sverdlov93 Aug 15, 2024
28ad0da
Update readme
sverdlov93 Aug 15, 2024
544b614
Update readme
sverdlov93 Aug 15, 2024
d5a4be1
Merge pull request #1 from sverdlov93/wrap-jf
sverdlov93 Aug 15, 2024
db4b4b0
Update readme
sverdlov93 Aug 15, 2024
8de3fe2
Merge branch 'wrap-jf' of https://github.com/sverdlov93/setup-jfrog-cli
sverdlov93 Aug 15, 2024
6cd42b3
Update readme
sverdlov93 Aug 15, 2024
e8d525f
Update readme
sverdlov93 Aug 15, 2024
e231848
Update readme
sverdlov93 Aug 15, 2024
b573e4f
Update readme
sverdlov93 Aug 15, 2024
adf6563
Update readme
sverdlov93 Aug 15, 2024
ea872b4
Update readme
sverdlov93 Aug 15, 2024
1171380
Update readme
sverdlov93 Aug 15, 2024
56dab90
Update readme
sverdlov93 Aug 15, 2024
f09231a
Update readme
sverdlov93 Aug 15, 2024
04d195f
Update readme
sverdlov93 Aug 15, 2024
9cb5134
Update readme
sverdlov93 Aug 15, 2024
d08cc92
Update readme
sverdlov93 Aug 18, 2024
888f122
Update readme
sverdlov93 Aug 18, 2024
c2d4d15
Update readme
sverdlov93 Aug 18, 2024
c7cbb07
Update readme
sverdlov93 Aug 18, 2024
3fa2037
Update readme
sverdlov93 Aug 18, 2024
bc9133f
Update readme
sverdlov93 Aug 18, 2024
4e9c301
Update readme
sverdlov93 Aug 18, 2024
17ec51e
Update readme
sverdlov93 Aug 18, 2024
80da577
Update readme
sverdlov93 Aug 18, 2024
90a1299
Merge branch 'master' of https://github.com/jfrog/setup-jfrog-cli
sverdlov93 Aug 18, 2024
a92a7c0
Update readme
sverdlov93 Aug 18, 2024
276f5e0
Update readme
sverdlov93 Aug 18, 2024
5c54acc
Update readme
sverdlov93 Aug 18, 2024
d3ba982
Update readme
sverdlov93 Aug 18, 2024
e3e08e9
Update readme
sverdlov93 Aug 18, 2024
6a4bcaa
Update readme
sverdlov93 Aug 18, 2024
70fe675
Update readme
sverdlov93 Aug 18, 2024
8219c1f
Update readme
sverdlov93 Aug 18, 2024
038aed3
Update readme
sverdlov93 Aug 18, 2024
78855a1
Merge branch 'master' of https://github.com/jfrog/setup-jfrog-cli
sverdlov93 Aug 19, 2024
9252b06
Update readme
sverdlov93 Aug 19, 2024
95541a5
Update readme
sverdlov93 Aug 19, 2024
9aa24aa
Update readme
sverdlov93 Aug 19, 2024
29eb3f4
Update readme
sverdlov93 Aug 19, 2024
16d94ec
Update readme
sverdlov93 Aug 19, 2024
73e5e40
Update readme
sverdlov93 Aug 19, 2024
a62388a
Update readme
sverdlov93 Aug 19, 2024
9b48600
Update readme
sverdlov93 Aug 19, 2024
c66bbbd
Update readme
sverdlov93 Aug 19, 2024
22db6ad
Update readme
sverdlov93 Aug 19, 2024
380e2a1
Update readme
sverdlov93 Aug 19, 2024
3a23f01
Update readme
sverdlov93 Aug 19, 2024
5663586
Update readme
sverdlov93 Aug 19, 2024
b086aa2
Update readme
sverdlov93 Aug 19, 2024
b6b8f89
Update readme
sverdlov93 Aug 19, 2024
0e8204f
Update readme
sverdlov93 Aug 19, 2024
13cf9b1
Merge branch 'master' of https://github.com/jfrog/setup-jfrog-cli
sverdlov93 Aug 20, 2024
d423b85
Update readme
sverdlov93 Aug 20, 2024
68ddd28
Update readme
sverdlov93 Aug 20, 2024
f2b7dea
Update readme
sverdlov93 Aug 20, 2024
1f4fa2f
Update readme
sverdlov93 Aug 20, 2024
6c77ee6
Update readme
sverdlov93 Aug 20, 2024
536a1ad
Update readme
sverdlov93 Aug 20, 2024
1d3b842
Update readme
sverdlov93 Aug 20, 2024
4f0bd45
Update readme
sverdlov93 Aug 20, 2024
491349f
Update readme
sverdlov93 Aug 20, 2024
586896c
Update readme
sverdlov93 Aug 20, 2024
bedaeca
Update readme
sverdlov93 Aug 20, 2024
c075b16
Update readme
sverdlov93 Aug 20, 2024
ef0d7fe
Update readme
sverdlov93 Aug 20, 2024
dad5ba9
Update readme
sverdlov93 Aug 20, 2024
f654f6f
Update readme
sverdlov93 Aug 20, 2024
bb0ac05
Update readme
sverdlov93 Aug 20, 2024
b8afd5f
Update readme
sverdlov93 Aug 20, 2024
471e448
Update readme
sverdlov93 Aug 20, 2024
0f383b9
Update readme
sverdlov93 Sep 1, 2024
0b2de96
Update readme
sverdlov93 Sep 1, 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
77 changes: 77 additions & 0 deletions .github/workflows/auto-build-publish-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Auto Build Publish Test
on:
push:
branches:
- master
# Triggers the workflow on labeled PRs only.
pull_request_target:
types: [ labeled ]
# Ensures that only the latest commit is running for each PR at a time.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.ref }}
cancel-in-progress: true

jobs:
Auto-Build-Publish-Test:
if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push'
strategy:
fail-fast: false
matrix:
os: [ ubuntu, windows, macos ]
runs-on: ${{ matrix.os }}-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Setup Go with cache
uses: jfrog/.github/actions/install-go-with-cache@main

- name: Install local Artifactory
uses: jfrog/.github/actions/install-local-artifactory@main
with:
RTLIC: ${{ secrets.RTLIC }}

- name: Post Step to Test the Auto Build-Publish post step
uses: gacts/run-and-post-run@v1
with:
post: |
jf c add --artifactory-url http://localhost:8081/artifactory --user admin --password password; \
count=$(jf rt search "artifactory-build-info/${GITHUB_WORKFLOW}/${GITHUB_RUN_NUMBER}-*" --count 2>stderr.log); \
exit_code=$?; \
cat stderr.log; \
if [ $exit_code -ne 0 ]; then \
echo "Command failed with exit code $exit_code."; \
exit 1; \
fi; \
if [ "$count" -eq 0 ]; then \
echo "No build info found."; \
exit 1; \
fi

- name: Setup JFrog CLI
id: setup-jfrog-cli
uses: ./
env:
JF_URL: http://localhost:8081/
JF_USER: admin
JF_PASSWORD: password

- name: Create NPM Remote Repository JSON
uses: jsdaniell/[email protected]
with:
name: "npm-remote-template.json"
json: '{
"key": "npm-remote",
"rclass": "remote",
"packageType": "npm",
"url": "https://registry.npmjs.org"
}'

- name: Configure Artifactory NPM Remote Repository
run: jf rt repo-create npm-remote-template.json
shell: bash

- name: Add npm modules to local build-info
run: |
jf npm-config --repo-resolve npm-remote
jf npm install
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ inputs:
description: "Set to true to disable the generation of Job Summaries."
default: "false"
required: false
disable-auto-build-publish:
description: "By default, if the workflow completes with collected build-info that has not been published using the jf rt build-publish command, the build-info will be automatically published to Artifactory. Set this to true to disable the automatic publication of build-info at the end of the workflow."
default: "false"
required: false
outputs:
oidc-token:
description: "JFrog OIDC token generated by the Setup JFrog CLI when setting oidc-provider-name."
Expand Down
73 changes: 67 additions & 6 deletions lib/cleanup.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,20 @@ 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.');
return;
}
try {
if (!addCachedJfToPath()) {
core.error('Could not find JFrog CLI path in the step state. Skipping cleanup.');
return;
if (!core.getBooleanInput(utils_1.Utils.AUTO_BUILD_PUBLISH_DISABLE)) {
yield collectAndPublishBuildInfoIfNeeded();
}
}
catch (error) {
core.warning('failed while attempting to publish build info: ' + error);
}
try {
core.startGroup('Cleanup JFrog CLI servers configuration');
yield utils_1.Utils.removeJFrogServers();
if (!core.getBooleanInput(utils_1.Utils.JOB_SUMMARY_DISABLE)) {
yield utils_1.Utils.generateWorkflowSummaryMarkdown();
Expand All @@ -56,12 +65,64 @@ 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 jfrogCliPath = core.getState(utils_1.Utils.JF_CLI_PATH_STATE);
if (!jfrogCliPath) {
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(jfrogCliPath);
core.addPath(jfCliPath);
return true;
}
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 {
// 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 });
// 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
}
finally {
core.exportVariable(utils_1.Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV, origValue);
}
});
}
function collectAndPublishBuildInfoIfNeeded() {
return __awaiter(this, void 0, void 0, function* () {
const workingDirectory = getWorkingDirectory();
// Check if there are any unpublished modules
if (!(yield hasUnpublishedModules(workingDirectory))) {
return;
}
// The flow here is to collect Git information before publishing the build info.
// 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');
yield utils_1.Utils.runCli(['rt', 'build-add-git'], { cwd: workingDirectory });
} catch (error) {
core.warning('failed while attempting to collect Git information: ' + error);
} 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() {
const workingDirectory = process.env.GITHUB_WORKSPACE;
if (!workingDirectory) {
throw new Error('GITHUB_WORKSPACE is not defined.');
}
return workingDirectory;
}
cleanup();
40 changes: 34 additions & 6 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ class Utils {
static enableJobSummaries() {
let commandSummariesOutputDir = process.env.RUNNER_TEMP;
if (commandSummariesOutputDir) {
Utils.exportVariableIfNotSet('JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR', commandSummariesOutputDir);
Utils.exportVariableIfNotSet(Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV, commandSummariesOutputDir);
}
}
static exportVariableIfNotSet(key, value) {
Expand Down Expand Up @@ -394,15 +394,39 @@ class Utils {
* This GitHub Action downloads the requested 'jfrog' executable and stores it as 'jfrog' and 'jf'.
* Therefore, the 'jf' executable is expected to be in the path also for older CLI versions.
* @param args - CLI arguments
* @param options - Execution options
*/
static runCli(args) {
static runCli(args, options) {
return __awaiter(this, void 0, void 0, function* () {
let res = yield (0, exec_1.exec)('jf', args);
let res = yield (0, exec_1.exec)('jf', args, options);
if (res !== core.ExitCode.Success) {
throw new Error('JFrog CLI exited with exit code ' + res);
}
});
}
/**
* Execute JFrog CLI command and capture its output.
* This GitHub Action downloads the requested 'jfrog' executable and stores it as 'jfrog' and 'jf'.
* Therefore, the 'jf' executable is expected to be in the path also for older CLI versions.
* The command's output is captured and returned as a string.
* The command is executed silently, meaning its output will not be printed to the console.
* If the command fails (i.e., exits with a non-success code), an error is thrown.
* @param args - CLI arguments
* @param options
* @returns The standard output of the CLI command as a string.
* @throws An error if the JFrog CLI command exits with a non-success code.
*/
static runCliAndGetOutput(args, options) {
return __awaiter(this, void 0, void 0, function* () {
let output = yield (0, exec_1.getExecOutput)('jf', args, options);
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);
}
return output.stdout;
});
}
/**
* If repository input was set, extract CLI download details,
* from either a Config Token with a JF_ENV_ prefix or separate env config (JF_URL, JF_USER, JF_PASSWORD, JF_ACCESS_TOKEN).
Expand Down Expand Up @@ -561,9 +585,9 @@ class Utils {
return `<a href="${projectPackagesUrl}">📦 Project ${projectKey} packages </a>` + '\n\n';
}
static getJobOutputDirectoryPath() {
const outputDir = process.env.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR;
const outputDir = process.env[Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV];
if (!outputDir) {
throw new Error('Jobs home directory is undefined, JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR is not set.');
throw new Error('Jobs home directory is undefined, ' + Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV + ' is not set.');
}
return path.join(outputDir, Utils.JOB_SUMMARY_DIR_NAME);
}
Expand Down Expand Up @@ -620,6 +644,8 @@ Utils.JF_CLI_PATH_STATE = 'JF_CLI_PATH_STATE';
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';
// Workflow summary section files. Order of sections in this array impacts the order in the final markdown.
Utils.JOB_SUMMARY_MARKDOWN_SECTIONS_NAMES = [
MarkdownSection.Security,
Expand All @@ -635,5 +661,7 @@ Utils.CLI_REMOTE_ARG = 'download-repository';
Utils.OIDC_AUDIENCE_ARG = 'oidc-audience';
// OpenID Connect provider_name input
Utils.OIDC_INTEGRATION_PROVIDER_NAME = 'oidc-provider-name';
// Job Summaries feature disable flag
// Disable Job Summaries feature flag
Utils.JOB_SUMMARY_DISABLE = 'disable-job-summary';
// Disable auto build info publish feature flag
Utils.AUTO_BUILD_PUBLISH_DISABLE = 'disable-auto-build-publish';
78 changes: 72 additions & 6 deletions src/cleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ import * as core from '@actions/core';
import { Utils } from './utils';

async function cleanup() {
if (!addCachedJfToPath()) {
core.error('Could not find JFrog CLI path in the step state. Skipping cleanup.');
return;
}
try {
if (!addCachedJfToPath()) {
core.error('Could not find JFrog CLI path in the step state. Skipping cleanup.');
return;
if (!core.getBooleanInput(Utils.AUTO_BUILD_PUBLISH_DISABLE)) {
await collectAndPublishBuildInfoIfNeeded();
}
} catch (error) {
core.warning('failed while attempting to publish build info: ' + error);
}

try {
core.startGroup('Cleanup JFrog CLI servers configuration');
await Utils.removeJFrogServers();
if (!core.getBooleanInput(Utils.JOB_SUMMARY_DISABLE)) {
await Utils.generateWorkflowSummaryMarkdown();
Expand All @@ -21,13 +29,71 @@ async function cleanup() {

function addCachedJfToPath(): boolean {
// Get the JFrog CLI path from step state. saveState/getState are methods to pass data between a step, and it's cleanup function.
const jfrogCliPath: string = core.getState(Utils.JF_CLI_PATH_STATE);
if (!jfrogCliPath) {
const jfCliPath: string = core.getState(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(jfrogCliPath);
core.addPath(jfCliPath);
return true;
}

interface BuildPublishResponse {
modules: any[];
}

async function hasUnpublishedModules(workingDirectory: string): Promise<boolean> {
// Save the old value of the environment variable to revert it later
const origValue: string | undefined = process.env[Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV];
try {
// Avoid saving a command summary for this dry-run command
core.exportVariable(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: string = await Utils.runCliAndGetOutput(['rt', 'build-publish', '--dry-run'], { silent: true, cwd: workingDirectory });

// Parse the JSON string to an object
const response: BuildPublishResponse = 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
} finally {
core.exportVariable(Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV, origValue);
}
}

async function collectAndPublishBuildInfoIfNeeded() {
const workingDirectory: string = getWorkingDirectory();
// Check if there are any unpublished modules
if (!(await hasUnpublishedModules(workingDirectory))) {
return;
}

// The flow here is to collect Git information before publishing the build info.
// 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');
await Utils.runCli(['rt', 'build-add-git'], { cwd: workingDirectory });
} catch (error) {
core.warning('failed while attempting to collect Git information: ' + error);
} finally {
core.endGroup();
}

core.startGroup('Publish the build info to JFrog Artifactory');
await Utils.runCli(['rt', 'build-publish'], { cwd: workingDirectory });
core.endGroup();
}

function getWorkingDirectory(): string {
const workingDirectory: string | undefined = process.env.GITHUB_WORKSPACE;
if (!workingDirectory) {
throw new Error('GITHUB_WORKSPACE is not defined.');
}
return workingDirectory;
}

cleanup();
Loading
Loading