From 1ce9b356f636ab9fc64803fdbc29299ce1ea248b Mon Sep 17 00:00:00 2001 From: Josh Dales Date: Sat, 18 Mar 2023 15:41:09 -0400 Subject: [PATCH] Move all changedFiles logic into it's own file --- __tests__/labeler.test.ts | 6 +- src/changedFiles.ts | 126 +++++++++++++++++++++++++++++++++++++ src/labeler.ts | 127 +++----------------------------------- 3 files changed, 134 insertions(+), 125 deletions(-) create mode 100644 src/changedFiles.ts diff --git a/__tests__/labeler.test.ts b/__tests__/labeler.test.ts index 6b322f21..0e81bce7 100644 --- a/__tests__/labeler.test.ts +++ b/__tests__/labeler.test.ts @@ -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', () => { diff --git a/src/changedFiles.ts b/src/changedFiles.ts new file mode 100644 index 00000000..3d7d7729 --- /dev/null +++ b/src/changedFiles.ts @@ -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; + +export async function getChangedFiles( + client: ClientType, + prNumber: number +): Promise { + 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; +} diff --git a/src/labeler.ts b/src/labeler.ts index 5effa71a..86927ec6 100644 --- a/src/labeler.ts +++ b/src/labeler.ts @@ -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; @@ -76,27 +75,6 @@ function getPrNumber(): number | undefined { return pullRequest.number; } -async function getChangedFiles( - client: ClientType, - prNumber: number -): Promise { - 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)) {