Move all changedFiles logic into it's own file

This commit is contained in:
Josh Dales
2023-03-18 15:41:09 -04:00
parent 9f259ee115
commit 1ce9b356f6
3 changed files with 134 additions and 125 deletions

View File

@@ -10,11 +10,7 @@ beforeAll(() => {
});
});
// I have to double cast here as this is what the output from js-yaml looks like which then gets
// transformed in toMatchConfig
const matchConfig = [
{'changed-files': [{any: ['*.txt']}]}
] as unknown as MatchConfig[];
const matchConfig: MatchConfig[] = [{changedFiles: {any: ['*.txt']}}];
describe('checkMatchConfigs', () => {
it('returns true when our pattern does match changed files', () => {

126
src/changedFiles.ts Normal file
View File

@@ -0,0 +1,126 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import {Minimatch} from 'minimatch';
export interface ChangedFilesMatchConfig {
changedFiles?: {
all?: string[];
any?: string[];
};
}
type ClientType = ReturnType<typeof github.getOctokit>;
export async function getChangedFiles(
client: ClientType,
prNumber: number
): Promise<string[]> {
const listFilesOptions = client.rest.pulls.listFiles.endpoint.merge({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
pull_number: prNumber
});
const listFilesResponse = await client.paginate(listFilesOptions);
const changedFiles = listFilesResponse.map((f: any) => f.filename);
core.debug('found changed files:');
for (const file of changedFiles) {
core.debug(' ' + file);
}
return changedFiles;
}
export function toChangedFilesMatchConfig(
config: any
): ChangedFilesMatchConfig {
if (!config['changed-files']) {
return {};
}
const changedFilesConfig = config['changed-files'];
// If the value provided is a string or an array of strings then default to `any` matching
if (typeof changedFilesConfig === 'string') {
return {
changedFiles: {
any: [changedFilesConfig]
}
};
}
const changedFilesMatchConfig = {
changedFiles: {}
};
if (Array.isArray(changedFilesConfig)) {
if (changedFilesConfig.every(entry => typeof entry === 'string')) {
changedFilesMatchConfig.changedFiles = {
any: changedFilesConfig
};
} else {
// If it is not an array of strings then it should be array of further config options
// so assign them to our `changedFilesMatchConfig`
Object.assign(
changedFilesMatchConfig.changedFiles,
...changedFilesConfig
);
Object.keys(changedFilesMatchConfig.changedFiles).forEach(key => {
const value = changedFilesMatchConfig.changedFiles[key];
changedFilesMatchConfig.changedFiles[key] = Array.isArray(value)
? value
: [value];
});
}
}
return changedFilesMatchConfig;
}
function printPattern(matcher: Minimatch): string {
return (matcher.negate ? '!' : '') + matcher.pattern;
}
function isMatch(changedFile: string, matchers: Minimatch[]): boolean {
core.debug(` matching patterns against file ${changedFile}`);
for (const matcher of matchers) {
core.debug(` - ${printPattern(matcher)}`);
if (!matcher.match(changedFile)) {
core.debug(` ${printPattern(matcher)} did not match`);
return false;
}
}
core.debug(` all patterns matched`);
return true;
}
// equivalent to "Array.some()" but expanded for debugging and clarity
export function checkAny(changedFiles: string[], globs: string[]): boolean {
const matchers = globs.map(g => new Minimatch(g));
core.debug(` checking "any" patterns`);
for (const changedFile of changedFiles) {
if (isMatch(changedFile, matchers)) {
core.debug(` "any" patterns matched against ${changedFile}`);
return true;
}
}
core.debug(` "any" patterns did not match any files`);
return false;
}
// equivalent to "Array.every()" but expanded for debugging and clarity
export function checkAll(changedFiles: string[], globs: string[]): boolean {
const matchers = globs.map(g => new Minimatch(g));
core.debug(` checking "all" patterns`);
for (const changedFile of changedFiles) {
if (!isMatch(changedFile, matchers)) {
core.debug(` "all" patterns did not match against ${changedFile}`);
return false;
}
}
core.debug(` "all" patterns matched all files`);
return true;
}

View File

@@ -1,17 +1,16 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import * as yaml from 'js-yaml';
import {Minimatch} from 'minimatch';
import {
ChangedFilesMatchConfig,
getChangedFiles,
toChangedFilesMatchConfig,
checkAny,
checkAll
} from './changedFiles';
import {checkBranch, toBranchMatchConfig, BranchMatchConfig} from './branch';
interface ChangedFilesMatchConfig {
changedFiles?: {
all?: string[];
any?: string[];
};
}
export type MatchConfig = ChangedFilesMatchConfig & BranchMatchConfig;
type ClientType = ReturnType<typeof github.getOctokit>;
@@ -76,27 +75,6 @@ function getPrNumber(): number | undefined {
return pullRequest.number;
}
async function getChangedFiles(
client: ClientType,
prNumber: number
): Promise<string[]> {
const listFilesOptions = client.rest.pulls.listFiles.endpoint.merge({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
pull_number: prNumber
});
const listFilesResponse = await client.paginate(listFilesOptions);
const changedFiles = listFilesResponse.map((f: any) => f.filename);
core.debug('found changed files:');
for (const file of changedFiles) {
core.debug(' ' + file);
}
return changedFiles;
}
async function getMatchConfigs(
client: ClientType,
configurationPath: string
@@ -148,49 +126,6 @@ function getLabelConfigMapFromObject(
return labelMap;
}
function toChangedFilesMatchConfig(config: any): ChangedFilesMatchConfig {
if (!config['changed-files']) {
return {};
}
const changedFilesConfig = config['changed-files'];
// If the value provided is a string or an array of strings then default to `any` matching
if (typeof changedFilesConfig === 'string') {
return {
changedFiles: {
any: [changedFilesConfig]
}
};
}
const changedFilesMatchConfig = {
changedFiles: {}
};
if (Array.isArray(changedFilesConfig)) {
if (changedFilesConfig.every(entry => typeof entry === 'string')) {
changedFilesMatchConfig.changedFiles = {
any: changedFilesConfig
};
} else {
// If it is not an array of strings then it should be array of further config options
// so assign them to our `changedFilesMatchConfig`
Object.assign(
changedFilesMatchConfig.changedFiles,
...changedFilesConfig
);
Object.keys(changedFilesMatchConfig.changedFiles).forEach(key => {
const value = changedFilesMatchConfig.changedFiles[key];
changedFilesMatchConfig.changedFiles[key] = Array.isArray(value)
? value
: [value];
});
}
}
return changedFilesMatchConfig;
}
function toMatchConfig(config: MatchConfig): MatchConfig {
const changedFilesConfig = toChangedFilesMatchConfig(config);
const branchConfig = toBranchMatchConfig(config);
@@ -201,10 +136,6 @@ function toMatchConfig(config: MatchConfig): MatchConfig {
};
}
function printPattern(matcher: Minimatch): string {
return (matcher.negate ? '!' : '') + matcher.pattern;
}
export function checkMatchConfigs(
changedFiles: string[],
matchConfigs: MatchConfig[]
@@ -219,50 +150,6 @@ export function checkMatchConfigs(
return true;
}
function isMatch(changedFile: string, matchers: Minimatch[]): boolean {
core.debug(` matching patterns against file ${changedFile}`);
for (const matcher of matchers) {
core.debug(` - ${printPattern(matcher)}`);
if (!matcher.match(changedFile)) {
core.debug(` ${printPattern(matcher)} did not match`);
return false;
}
}
core.debug(` all patterns matched`);
return true;
}
// equivalent to "Array.some()" but expanded for debugging and clarity
function checkAny(changedFiles: string[], globs: string[]): boolean {
const matchers = globs.map(g => new Minimatch(g));
core.debug(` checking "any" patterns`);
for (const changedFile of changedFiles) {
if (isMatch(changedFile, matchers)) {
core.debug(` "any" patterns matched against ${changedFile}`);
return true;
}
}
core.debug(` "any" patterns did not match any files`);
return false;
}
// equivalent to "Array.every()" but expanded for debugging and clarity
function checkAll(changedFiles: string[], globs: string[]): boolean {
const matchers = globs.map(g => new Minimatch(g));
core.debug(` checking "all" patterns`);
for (const changedFile of changedFiles) {
if (!isMatch(changedFile, matchers)) {
core.debug(` "all" patterns did not match against ${changedFile}`);
return false;
}
}
core.debug(` "all" patterns matched all files`);
return true;
}
function checkMatch(changedFiles: string[], matchConfig: MatchConfig): boolean {
if (matchConfig.changedFiles?.all) {
if (!checkAll(changedFiles, matchConfig.changedFiles.all)) {