Skip to content

Commit

Permalink
write github outputs in github action using appendFileSync #3481
Browse files Browse the repository at this point in the history
  • Loading branch information
hamidonos committed Oct 25, 2024
1 parent 1ccaa65 commit 04fb4c1
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 8 deletions.
55 changes: 52 additions & 3 deletions github-actions/scan/__test__/post-scan.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,25 @@ import * as core from '@actions/core';
import { collectReportData, reportOutputs } from '../src/post-scan';
import { getReport } from '../src/sechub-cli';
import { LAUNCHER_CONTEXT_DEFAULTS } from '../src/launcher';
import { readFileSync, appendFileSync } from 'fs-extra';
import * as os from "node:os";

jest.mock('@actions/core');
const mockedCore = core as jest.Mocked<typeof core>;

jest.mock('../src/sechub-cli');
const mockedGetReport = getReport as jest.MockedFunction<typeof getReport>;

jest.mock('fs-extra', () => ({
writeFile: jest.fn(),
readFileSync: jest.fn(),
appendFileSync: jest.fn()
}));

const mockedReadFileSync = readFileSync as jest.MockedFunction<typeof readFileSync>;
const mockedAppendFileSync = appendFileSync as jest.MockedFunction<typeof appendFileSync>;
process.env['GITHUB_OUTPUT'] = 'dummy-file';

describe('collectReportData', function () {
afterEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -74,14 +86,12 @@ describe('collectReportData', function () {

it('calls getReport with parameters (except json) and report json object is as expected', function () {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fsMock = require('fs');

/* prepare */
const testContext = Object.create(LAUNCHER_CONTEXT_DEFAULTS);
testContext.reportFormats= ['json','html','xyz','bla'];
testContext.jobUUID=1234; // necessary for download

fsMock.readFileSync = jest.fn(() => '{"test": "test"}'); // Mock an empty JSON report
mockedReadFileSync.mockReturnValue('{"test": "test"}')
const sampleJson = {'test': 'test'};

/* execute */
Expand Down Expand Up @@ -136,21 +146,45 @@ describe('reportOutputs', function () {

/* test */
expect(mockedCore.debug).toHaveBeenCalledTimes(6);
expect(mockedAppendFileSync).toHaveBeenCalledTimes(6);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-trafficlight=RED${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-count=2${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-high=1${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-medium=0${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-low=1${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-readable-summary=SecHub reported traffic light color RED with 2 findings, categorized as follows: HIGH (1), LOW (1)${os.EOL}`);

/* Disabled until GitHub Action setOutput is fixed
expect(mockedCore.setOutput).toHaveBeenCalledTimes(6);
expect(mockedCore.setOutput).toBeCalledWith('scan-trafficlight', 'RED');
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-count', '2');
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-high', '1');
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-medium', '0');
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-low', '1');
expect(mockedCore.setOutput).toBeCalledWith('scan-readable-summary', 'SecHub reported traffic light color RED with 2 findings, categorized as follows: HIGH (1), LOW (1)');
*/
});

it('calls set github output with correct values when JSON report did not exist', function () {
/* execute */
reportOutputs(undefined);

/* test */

expect(mockedCore.debug).toHaveBeenCalledTimes(7);
expect(mockedAppendFileSync).toHaveBeenCalledTimes(6);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-trafficlight=FAILURE${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-count=0${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-high=0${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-medium=0${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-low=0${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-readable-summary=SecHub scan could not be executed.${os.EOL}`);


/* Disabled until GitHub Action setOutput is fixed
expect(mockedCore.debug).toBeCalledWith('No findings reported to be categorized.');
expect(mockedCore.setOutput).toHaveBeenCalledTimes(6);
expect(mockedCore.setOutput).toBeCalledWith('scan-trafficlight', 'FAILURE');
Expand All @@ -159,6 +193,8 @@ describe('reportOutputs', function () {
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-medium', '0');
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-low', '0');
expect(mockedCore.setOutput).toBeCalledWith('scan-readable-summary', 'SecHub scan could not be executed.');
*/
});

it('calls set github output with correct values when traffic light is green without findings.', function () {
Expand All @@ -180,13 +216,26 @@ describe('reportOutputs', function () {

/* test */
expect(mockedCore.debug).toHaveBeenCalledTimes(6);
expect(mockedAppendFileSync).toHaveBeenCalledTimes(6);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-trafficlight=GREEN${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-count=0${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-high=0${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-medium=0${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-findings-low=0${os.EOL}`);
expect(mockedAppendFileSync).toBeCalledWith(expect.any(String), `scan-readable-summary=SecHub reported traffic light color GREEN without findings${os.EOL}`);


/* Disabled until GitHub Action setOutput is fixed
expect(mockedCore.setOutput).toHaveBeenCalledTimes(6);
expect(mockedCore.setOutput).toBeCalledWith('scan-trafficlight', 'GREEN');
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-count', '0');
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-high', '0');
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-medium', '0');
expect(mockedCore.setOutput).toBeCalledWith('scan-findings-low', '0');
expect(mockedCore.setOutput).toBeCalledWith('scan-readable-summary', 'SecHub reported traffic light color GREEN without findings');
*/
});
});

19 changes: 14 additions & 5 deletions github-actions/scan/src/post-scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

import * as artifact from '@actions/artifact';
import * as core from '@actions/core';
import * as fs from 'fs';
import { getWorkspaceDir } from './fs-helper';
import { LaunchContext } from './launcher';
import { logExitCode } from './exitcode';
import { getReport } from './sechub-cli';
import { getFieldFromJson } from './json-helper';
import { execFileSync } from "child_process";
import { sanitize } from "./shell-arg-sanitizer";
import { readFileSync, appendFileSync} from "fs-extra";
import * as os from "node:os";

const NEW_LINE_SEPARATOR = '\n';

Expand All @@ -33,7 +34,7 @@ function collectJsonReportData(context: LaunchContext) {
let text = '';
try {
core.info('Get Report as json');
text = fs.readFileSync(filePath, 'utf8');
text = readFileSync(filePath, 'utf8');
} catch (error) {
core.warning(`Error reading JSON file: ${error}`);
return undefined;
Expand Down Expand Up @@ -276,9 +277,17 @@ function buildSummary(trafficLight: string, totalFindings: number, findings: { m
* @param {string} dataFormat - The desired data format ('string' or 'number').
*/
function setOutput(field: string, value: any, dataFormat: string) {

value = value ?? (dataFormat === 'number' ? 0 : 'FAILURE');

core.debug(`Output ${field} set to ${value}`);
core.setOutput(field, value.toString()); // Ensure value is converted to a string as GitHub Actions expects output variables to be strings.
}
/*
* Disabling this until GitHub releases a fix for this. See: https://github.com/actions/toolkit/issues/1218
* core.setOutput(field, value.toString()); // Ensure value is converted to a string as GitHub Actions expects output variables to be strings.
*/

/* Temporary hack until core actions output is fixed */
const output = process.env['GITHUB_OUTPUT']
if (output) {
appendFileSync(output, `${field}=${value}${os.EOL}`)
}
}

0 comments on commit 04fb4c1

Please sign in to comment.