Skip to content

Commit

Permalink
Command Summary - New UI (#186)
Browse files Browse the repository at this point in the history
  • Loading branch information
EyalDelarea authored Sep 1, 2024
1 parent a978f6e commit c462cde
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 174 deletions.
1 change: 0 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ jobs:
# Checkout and install prerequisites
- name: Checkout
uses: actions/checkout@v4

- name: Setup NodeJS
uses: actions/setup-node@v4
with:
Expand Down
2 changes: 1 addition & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ author: "JFrog"
inputs:
version:
description: "JFrog CLI Version"
default: "2.63.2"
default: "2.66.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."
Expand Down
Binary file modified images/job_summary.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/summary_header.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 20 additions & 5 deletions lib/cleanup.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,34 @@ function cleanup() {
core.error('Could not find JFrog CLI path in the step state. Skipping cleanup.');
return;
}
// Auto-publish build info if needed
try {
if (!core.getBooleanInput(utils_1.Utils.AUTO_BUILD_PUBLISH_DISABLE)) {
core.startGroup('Build Info Auto-Publish');
yield collectAndPublishBuildInfoIfNeeded();
core.endGroup();
}
}
catch (error) {
core.warning('failed while attempting to publish build info: ' + error);
}
// Generate job summary
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();
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);
}
// Cleanup JFrog CLI servers configuration
try {
core.startGroup('Cleanup JFrog CLI servers configuration');
yield utils_1.Utils.removeJFrogServers();
}
catch (error) {
core.setFailed(error.message);
}
Expand Down Expand Up @@ -108,9 +121,11 @@ function collectAndPublishBuildInfoIfNeeded() {
try {
core.startGroup('Collect the Git information');
yield utils_1.Utils.runCli(['rt', 'build-add-git'], { cwd: workingDirectory });
} catch (error) {
}
catch (error) {
core.warning('failed while attempting to collect Git information: ' + error);
} finally {
}
finally {
core.endGroup();
}
core.startGroup('Publish the build info to JFrog Artifactory');
Expand Down
111 changes: 41 additions & 70 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,18 +475,18 @@ class Utils {
return;
}
/**
* Generates GitHub workflow Summary Markdown.
* Generates GitHub workflow unified Summary report.
* This function runs as part of post-workflow cleanup function,
* collects existing section markdown files generated by the CLI,
* and constructs a single markdown file, to be displayed in the GitHub UI.
* and constructs a single Markdown file, to be displayed in the GitHub UI.
*/
static generateWorkflowSummaryMarkdown() {
static setMarkdownAsJobSummary() {
return __awaiter(this, void 0, void 0, function* () {
try {
// Read all sections and construct the final markdown file
const markdownContent = yield this.readCLIMarkdownSectionsAndWrap();
// Read all sections and construct the final Markdown file
const markdownContent = yield this.readCommandSummaryMarkdown();
if (markdownContent.length == 0) {
core.debug('No job summaries sections found. Workflow summary will not be generated.');
core.debug('No job summary file found. Workflow summary will not be generated.');
return;
}
// Write to GitHub's job summary
Expand All @@ -505,68 +505,37 @@ class Utils {
* This function reads each section file and wraps it with a markdown header
* @returns <string> the content of the markdown file as string, warped in a collapsable section.
*/
static readCLIMarkdownSectionsAndWrap() {
static readCommandSummaryMarkdown() {
return __awaiter(this, void 0, void 0, function* () {
const outputDir = Utils.getJobOutputDirectoryPath();
let markdownContent = '';
const sectionContents = {};
// Read all sections.
for (const sectionName of Utils.JOB_SUMMARY_MARKDOWN_SECTIONS_NAMES) {
const fullPath = path.join(outputDir, sectionName, 'markdown.md');
if ((0, fs_1.existsSync)(fullPath)) {
sectionContents[sectionName] = yield Utils.readSummarySection(fullPath, sectionName);
}
}
// If build info was published, remove generic upload section to avoid duplications with generic modules.
if (sectionContents[MarkdownSection.BuildInfo] != '') {
sectionContents[MarkdownSection.Upload] = '';
}
// Append sections in order.
for (const sectionName of Utils.JOB_SUMMARY_MARKDOWN_SECTIONS_NAMES) {
markdownContent += sectionContents[sectionName] || '';
let markdownContent = yield Utils.readMarkdownContent();
if (markdownContent === '') {
return '';
}
return markdownContent ? Utils.wrapContent(markdownContent) : '';
// Check if the header can be accessed via the internet to decide if to use the image or the text header
this.isSummaryHeaderAccessible = yield this.isHeaderPngAccessible();
core.debug('Header image is accessible: ' + this.isSummaryHeaderAccessible);
return Utils.wrapContent(markdownContent);
});
}
static readSummarySection(fullPath, section) {
static readMarkdownContent() {
return __awaiter(this, void 0, void 0, function* () {
let content = '';
try {
content = yield fs_1.promises.readFile(fullPath, 'utf-8');
return Utils.wrapCollapsableSection(section, content);
}
catch (error) {
throw new Error('failed to read section file: ' + fullPath + ' ' + error);
const outputDir = Utils.getJobOutputDirectoryPath();
if ((0, fs_1.existsSync)(outputDir)) {
return yield fs_1.promises.readFile(path.join(outputDir, 'markdown.md'), 'utf-8');
}
return '';
});
}
static getMarkdownHeader() {
let mainTitle;
if (Utils.isColorSchemeSupported()) {
mainTitle = `# $\\textcolor{green}{\\textsf{ 🐸 JFrog Job Summary}}$` + '\n\n';
if (this.isSummaryHeaderAccessible) {
mainTitle = `<picture><img alt="Summary-Header" src=${this.MARKDOWN_HEADER_PNG_URL}></picture>` + '\n\n';
}
else {
mainTitle = `# 🐸 JFrog Job Summary` + '\n\n';
}
return mainTitle + Utils.getProjectPackagesLink();
}
/**
* Check if the color scheme is supported in the GitHub UI.
* Currently, GitHub enterprise does not support the color LaTex scheme $\textcolor{}.
* This scheme is part of the LaTeX/Mathematics scheme.
*
* Currently, the scheme is not supported by GitHub Enterprise version 3.13,
* which is the latest version at the time of writing this comment.
*
* For more info about the scheme see:
* https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/writing-mathematical-expressions
*
* @returns <boolean> true if the color scheme is supported, false otherwise.
*/
static isColorSchemeSupported() {
let serverUrl = process.env.GITHUB_SERVER_URL || '';
return serverUrl.startsWith('https://github.com');
}
/**
* Gets the project packages link to be displayed in the summary
* If the project is undefined, it will resolve to 'all' section in the UI.
Expand All @@ -582,7 +551,7 @@ class Utils {
}
let projectKey = process.env.JF_PROJECT ? process.env.JF_PROJECT : '';
let projectPackagesUrl = platformUrl + 'ui/packages' + '?projectKey=' + projectKey;
return `<a href="${projectPackagesUrl}">📦 Project ${projectKey} packages </a>` + '\n\n';
return `<a href="${projectPackagesUrl}"> 🐸 View package details on the JFrog platform </a>` + '\n\n';
}
static getJobOutputDirectoryPath() {
const outputDir = process.env[Utils.JFROG_CLI_COMMAND_SUMMARY_OUTPUT_DIR_ENV];
Expand All @@ -598,29 +567,29 @@ class Utils {
yield fs_1.promises.rm(outputDir, { recursive: true });
});
}
static wrapCollapsableSection(section, markdown) {
let sectionTitle;
switch (section) {
case MarkdownSection.Upload:
sectionTitle = `📁 Files uploaded to Artifactory by this workflow`;
break;
case MarkdownSection.BuildInfo:
sectionTitle = `📦 Build info published to Artifactory by this workflow`;
break;
case MarkdownSection.Security:
sectionTitle = `🔒 Security Status`;
break;
default:
throw new Error(`Failed to get unknown section: ${section}, title.`);
}
return `\n\n\n<details open>\n\n<summary> ${sectionTitle} </summary><p></p> \n\n ${markdown} \n\n</details>\n\n\n`;
}
static wrapContent(fileContent) {
return Utils.getMarkdownHeader() + fileContent + Utils.getMarkdownFooter();
}
static getMarkdownFooter() {
return '\n\n # \n\n The above Job Summary was generated by the <a href="https://github.com/jfrog/setup-jfrog-cli/blob/master/README.md#jfrog-job-summary"> Setup JFrog CLI GitHub Action </a>';
}
static isHeaderPngAccessible() {
return __awaiter(this, void 0, void 0, function* () {
const url = this.MARKDOWN_HEADER_PNG_URL;
const httpClient = new http_client_1.HttpClient();
try {
const response = yield httpClient.head(url);
return response.message.statusCode === 200;
}
catch (error) {
core.warning('No internet access to the header image, using the text header instead.');
return false;
}
finally {
httpClient.dispose();
}
});
}
}
exports.Utils = Utils;
// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand Down Expand Up @@ -665,3 +634,5 @@ Utils.OIDC_INTEGRATION_PROVIDER_NAME = 'oidc-provider-name';
Utils.JOB_SUMMARY_DISABLE = 'disable-job-summary';
// Disable auto build info publish feature flag
Utils.AUTO_BUILD_PUBLISH_DISABLE = 'disable-auto-build-publish';
// Source URL holding the markdown header image
Utils.MARKDOWN_HEADER_PNG_URL = 'https://media.jfrog.com/wp-content/uploads/2024/09/01120106/summary_header.png';
19 changes: 15 additions & 4 deletions src/cleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,31 @@ async function cleanup() {
core.error('Could not find JFrog CLI path in the step state. Skipping cleanup.');
return;
}
// Auto-publish build info if needed
try {
if (!core.getBooleanInput(Utils.AUTO_BUILD_PUBLISH_DISABLE)) {
core.startGroup('Build Info Auto-Publish');
await collectAndPublishBuildInfoIfNeeded();
core.endGroup();
}
} catch (error) {
core.warning('failed while attempting to publish build info: ' + error);
}

// Generate job summary
try {
core.startGroup('Cleanup JFrog CLI servers configuration');
await Utils.removeJFrogServers();
if (!core.getBooleanInput(Utils.JOB_SUMMARY_DISABLE)) {
await Utils.generateWorkflowSummaryMarkdown();
core.startGroup('Generating Job Summary');
await Utils.runCli(['generate-summary-markdown']);
await Utils.setMarkdownAsJobSummary();
core.endGroup();
}
} catch (error) {
core.warning('failed while attempting to generate job summary: ' + error);
}
// Cleanup JFrog CLI servers configuration
try {
core.startGroup('Cleanup JFrog CLI servers configuration');
await Utils.removeJFrogServers();
} catch (error) {
core.setFailed((<any>error).message);
} finally {
Expand Down
Loading

0 comments on commit c462cde

Please sign in to comment.