Skip to content
Closed
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
8 changes: 8 additions & 0 deletions common/src/common-utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { setOutput } from '@actions/core';
import { getExecOutput } from '@actions/exec'
import { stringifyForShell } from './serialization-utils';

export async function execCommand(command: string): Promise<string> {
const { stdout, stderr, exitCode } = await getExecOutput(command)
Expand All @@ -9,3 +11,9 @@ export async function execCommand(command: string): Promise<string> {

return stdout.trim()
}

export function setOutputs(values: Record<string, unknown>): void {
for (const [key, value] of Object.entries(values)) {
setOutput(key, stringifyForShell(value));
}
}
1 change: 0 additions & 1 deletion common/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

export const inputs = {
GH_TOKEN: 'gh-token',
OUTPUT: 'output',
PATHS: 'paths',
} as const;

Expand Down
5 changes: 5 additions & 0 deletions common/src/path-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ describe('path utils', () => {
patterns: [],
expected: []
},
{
paths: ['a.ts', 'a.js', 'b.md'],
patterns: [],
expected: ['a.ts', 'a.js', 'b.md']
},
{
paths: ['a.ts', 'a.js', 'b.md'],
patterns: ['b*.*'],
Expand Down
18 changes: 11 additions & 7 deletions common/src/path-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ function filterPathsImpl(
paths: string[],
patterns: string[],
): string[] {
return paths.filter(path => {
return patterns.reduce((prevResult, pattern) => {
return pattern.startsWith(NEGATION)
? prevResult && !match(path, pattern.substring(1))
: prevResult || match(path, pattern);
}, false);
});
return patterns?.length === 0
? paths
: paths.filter(path => testPath(path, patterns));
}

export function testPath(path: string, patterns: string[]): boolean {
return patterns.reduce((prevResult, pattern) => {
return pattern.startsWith(NEGATION)
? prevResult && !match(path, pattern.substring(1))
: prevResult || match(path, pattern);
}, false);
}
18 changes: 12 additions & 6 deletions common/src/pr-utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

import * as core from '@actions/core'
import { context, getOctokit } from '@actions/github'
import * as core from '@actions/core';
import { context, getOctokit } from '@actions/github';
import { components } from '@octokit/openapi-types';
import { execCommand } from './common-utils';

export async function getPrRevisionRange(): Promise<{
Expand Down Expand Up @@ -42,14 +43,19 @@ function normalizeCommit(commit: string) {
return commit === '0000000000000000000000000000000000000000' ? 'HEAD^' : commit;
}

export async function getChangedFiles(token: string): Promise<string[]> {
interface ChangedFile {
path: string;
status: components['schemas']['diff-entry']['status'];
}

export async function getChangedFiles(token: string): Promise<ChangedFile[]> {
return getChangedFilesImpl(token).then((files) => {
core.info(`${files.length} changed files: ${JSON.stringify(files, undefined, 2)}`)
return files;
});
}

async function getChangedFilesImpl(token: string): Promise<string[]> {
async function getChangedFilesImpl(token: string): Promise<ChangedFile[]> {
try {
const octokit = getOctokit(token);

Expand All @@ -58,13 +64,13 @@ async function getChangedFilesImpl(token: string): Promise<string[]> {
return [];
}

const files = await octokit.paginate(octokit.rest.pulls.listFiles, {
const entries = await octokit.paginate(octokit.rest.pulls.listFiles, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
});

return files.map(file => file.filename);
return entries.map(({ filename, status }) => ({ path: filename, status }));
} catch (error) {
core.setFailed(`Getting changed files failed with error: ${error}`);
return [];
Expand Down
23 changes: 23 additions & 0 deletions common/src/serialization-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { stringifyForShell } from "./serialization-utils";

describe('action utils', () => {

describe(stringifyForShell.name, () => {
test.each([
{ value: 123, expected: '123' },
{ value: 'abc', expected: 'abc' },
])('scalar cases [%#]', ({ value, expected }) => {
expect(stringifyForShell(value)).toEqual(expected);
});
});

describe(stringifyForShell.name, () => {
test.each([
{ value: [123, 456], expected: '123 456' },
{ value: ['abc', 'def'], expected: '\'abc\' \'def\'' },
])('array values [%#]', ({ value, expected }) => {
expect(stringifyForShell(value)).toEqual(expected);
});
});

});
35 changes: 35 additions & 0 deletions common/src/serialization-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
function stringifyArrayItem(item: unknown): string {
switch (typeof item) {
case 'number':
return item.toString();

case 'string':
return `'${item}'`;

default:
return JSON.stringify(item);
}
}

export function stringifyForShell(value: unknown): string {

switch (typeof value) {

case 'string':
return value;

case 'object':
if (Array.isArray(value)) {
return value.map(stringifyArrayItem).join(' ');
}

if (value === null) {
return '';
}

return value.toString();

default:
return JSON.stringify(value);
}
}
5 changes: 0 additions & 5 deletions get-changed-files/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ inputs:
description: Semicolon separated globs
required: false

output:
description: Output file path
required: true


runs:
using: node16
main: dist/index.js
Expand Down
89 changes: 72 additions & 17 deletions get-changed-files/dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.execCommand = void 0;
exports.setOutputs = exports.execCommand = void 0;
const core_1 = __nccwpck_require__(5316);
const exec_1 = __nccwpck_require__(110);
const serialization_utils_1 = __nccwpck_require__(9091);
function execCommand(command) {
return __awaiter(this, void 0, void 0, function* () {
const { stdout, stderr, exitCode } = yield (0, exec_1.getExecOutput)(command);
Expand All @@ -28,6 +30,12 @@ function execCommand(command) {
});
}
exports.execCommand = execCommand;
function setOutputs(values) {
for (const [key, value] of Object.entries(values)) {
(0, core_1.setOutput)(key, (0, serialization_utils_1.stringifyForShell)(value));
}
}
exports.setOutputs = setOutputs;


/***/ }),
Expand All @@ -41,7 +49,6 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.outputs = exports.inputs = void 0;
exports.inputs = {
GH_TOKEN: 'gh-token',
OUTPUT: 'output',
PATHS: 'paths',
};
exports.outputs = {
Expand Down Expand Up @@ -126,7 +133,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.filterPaths = void 0;
exports.testPath = exports.filterPaths = void 0;
const core = __importStar(__nccwpck_require__(5316));
const minimatch_1 = __nccwpck_require__(148);
const NEGATION = '!';
Expand All @@ -144,14 +151,18 @@ function filterPaths(paths, patterns) {
}
exports.filterPaths = filterPaths;
function filterPathsImpl(paths, patterns) {
return paths.filter(path => {
return patterns.reduce((prevResult, pattern) => {
return pattern.startsWith(NEGATION)
? prevResult && !match(path, pattern.substring(1))
: prevResult || match(path, pattern);
}, false);
});
return (patterns === null || patterns === void 0 ? void 0 : patterns.length) === 0
? paths
: paths.filter(path => testPath(path, patterns));
}
function testPath(path, patterns) {
return patterns.reduce((prevResult, pattern) => {
return pattern.startsWith(NEGATION)
? prevResult && !match(path, pattern.substring(1))
: prevResult || match(path, pattern);
}, false);
}
exports.testPath = testPath;


/***/ }),
Expand Down Expand Up @@ -249,12 +260,12 @@ function getChangedFilesImpl(token) {
core.setFailed('Getting changed files only works on pull request events.');
return [];
}
const files = yield octokit.paginate(octokit.rest.pulls.listFiles, {
const entries = yield octokit.paginate(octokit.rest.pulls.listFiles, {
owner: github_1.context.repo.owner,
repo: github_1.context.repo.repo,
pull_number: github_1.context.payload.pull_request.number,
});
return files.map(file => file.filename);
return entries.map(({ filename, status }) => ({ path: filename, status }));
}
catch (error) {
core.setFailed(`Getting changed files failed with error: ${error}`);
Expand All @@ -264,6 +275,44 @@ function getChangedFilesImpl(token) {
}


/***/ }),

/***/ 9091:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.stringifyForShell = void 0;
function stringifyArrayItem(item) {
switch (typeof item) {
case 'number':
return item.toString();
case 'string':
return `'${item}'`;
default:
return JSON.stringify(item);
}
}
function stringifyForShell(value) {
switch (typeof value) {
case 'string':
return value;
case 'object':
if (Array.isArray(value)) {
return value.map(stringifyArrayItem).join(' ');
}
if (value === null) {
return '';
}
return value.toString();
default:
return JSON.stringify(value);
}
}
exports.stringifyForShell = stringifyForShell;


/***/ }),

/***/ 2013:
Expand Down Expand Up @@ -514,20 +563,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
const fs = __importStar(__nccwpck_require__(7147));
const core = __importStar(__nccwpck_require__(5316));
const common_1 = __nccwpck_require__(9145);
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
const pathPatterns = core.getInput(common_1.inputs.PATHS).split(';');
const token = core.getInput(common_1.inputs.GH_TOKEN, { required: true });
const output = core.getInput(common_1.inputs.OUTPUT, { required: true });
console.log('patterns: ' + JSON.stringify(pathPatterns, undefined, 2));
const changedFiles = yield (0, common_1.getChangedFiles)(token);
const filteredFiles = (0, common_1.filterPaths)(changedFiles, pathPatterns);
(0, common_1.ensureDir)(output);
fs.writeFileSync(output, JSON.stringify(filteredFiles.map(filename => ({ filename })), undefined, 2));
const filteredFiles = pathPatterns.length > 0
? changedFiles.filter(({ path }) => (0, common_1.testPath)(path, pathPatterns))
: changedFiles;
(0, common_1.setOutputs)({
json: JSON.stringify({
files: filteredFiles,
count: filteredFiles.length,
}),
files: filteredFiles.map(e => e.path),
count: filteredFiles.length,
});
}
catch (error) {
if (error instanceof Error) {
Expand Down
23 changes: 18 additions & 5 deletions get-changed-files/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
import * as fs from 'fs';
import * as core from '@actions/core';

import { inputs, filterPaths, getChangedFiles, ensureDir } from 'common';
import {
inputs,
getChangedFiles,
ensureDir,
setOutputs,
testPath,
} from 'common';


async function run(): Promise<void> {
try {
const pathPatterns = core.getInput(inputs.PATHS).split(';');
const token = core.getInput(inputs.GH_TOKEN, { required: true });
const output = core.getInput(inputs.OUTPUT, { required: true });

console.log('patterns: ' + JSON.stringify(pathPatterns, undefined, 2));

const changedFiles = await getChangedFiles(token);
const filteredFiles = filterPaths(changedFiles, pathPatterns);
const filteredFiles = pathPatterns.length > 0
? changedFiles.filter(({ path }) => testPath(path, pathPatterns))
: changedFiles;

ensureDir(output);
fs.writeFileSync(output, JSON.stringify(filteredFiles.map(filename => ({ filename })), undefined, 2));
setOutputs({
json: JSON.stringify({
files: filteredFiles,
count: filteredFiles.length,
}),
files: filteredFiles.map(e => e.path),
count: filteredFiles.length,
});
} catch (error) {
if (error instanceof Error) {
core.setFailed(error.message)
Expand Down
Loading