-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[affected][newfeature]: cli for affected task (#17)
[affected][newfeature]: cli for affected task (#17)
- Loading branch information
1 parent
fb21e88
commit d112a2b
Showing
17 changed files
with
422 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
peggy-parser: 'apps/affected/src/parser.peggy'; | ||
peggy-parser-checkIf-incomplete: peggy-parser AND (!'apps/affected/src/parser.ts' OR !'apps/affected/src/parser.spec.ts'); | ||
|
||
<affected>: './apps/affected/**' './dist/apps/affected/**'; | ||
<affected>: './apps/affected/**' './dist/apps/affected/**' './package.json'; | ||
<version-autopilot>: './apps/version-autopilot/**' './dist/apps/version-autopilot/**'; | ||
<pragma>: './apps/pragma/**' './dist/apps/pragma/**'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import fs from 'fs'; | ||
import path from 'path'; | ||
import { getChangedFiles, writeChangedFiles } from './changedFiles'; | ||
import { evaluateStatementsForChanges } from './evaluateStatementsForChanges'; | ||
import { allGitFiles, evaluateStatementsForHashes } from './evaluateStatementsForHashes'; | ||
import { parse } from './parser'; | ||
import { AST } from './parser.types'; | ||
|
||
export interface ImageContext { | ||
event: string; | ||
pull_request_number: number; | ||
} | ||
|
||
export const getRules = (rulesInput: string, rulesFile: string) => { | ||
if (rulesInput && rulesFile) { | ||
throw new Error("Only one of 'rules' or 'rules-file' can be specified. Please use either one."); | ||
} | ||
|
||
if (!rulesInput && !rulesFile) { | ||
throw new Error("You must specify either 'rules' or 'rules-file'."); | ||
} | ||
|
||
let rules = ''; | ||
if (rulesInput) { | ||
rules = rulesInput; | ||
} else { | ||
const rulesFilePath = path.resolve(rulesFile); | ||
if (!fs.existsSync(rulesFilePath)) { | ||
throw new Error(`The specified rules-file does not exist: ${rulesFilePath}`); | ||
} | ||
|
||
rules = fs.readFileSync(rulesFilePath, 'utf8'); | ||
} | ||
return rules; | ||
}; | ||
|
||
|
||
|
||
export const getImageName = (appTarget: string, sha: string, truncateSha1Size = 0, imageTagRegistry = '', imageTagPrefix = '', imageTagSuffix = '', imageContext?: ImageContext) => { | ||
let sha1 = sha; | ||
if (isNaN(truncateSha1Size) || truncateSha1Size === 0) { | ||
sha1 = sha; | ||
} else if (truncateSha1Size > 0) { | ||
sha1 = sha.slice(0, truncateSha1Size); | ||
} else { | ||
sha1 = sha.slice(truncateSha1Size); | ||
} | ||
|
||
const imageName1 = `${appTarget}:${imageTagPrefix}${sha1}${imageTagSuffix}`; | ||
|
||
let imageName2 = `${appTarget}:latest`; | ||
if (imageContext && imageContext.event === 'pull_request') { | ||
imageName2 = `${appTarget}:pr-${imageContext.pull_request_number}`; | ||
} | ||
|
||
return [imageName1, imageName2].map((imageName) => `${imageTagRegistry || ''}${imageName}`); | ||
} | ||
|
||
export const processRules = async ( | ||
log: (message: string) => void, | ||
rulesInput: string, | ||
truncateSha1Size: number, | ||
imageTagRegistry: string, | ||
imageTagPrefix: string, | ||
imageTagSuffix: string, | ||
changedFilesOutputFile?: string, | ||
imageContext?: ImageContext) => { | ||
const affectedImageTags: Record<string, string[]> = {}; | ||
const affectedShas: Record<string, string> = {}; | ||
const affectedChanges: Record<string, boolean> = {}; | ||
|
||
if (rulesInput) { | ||
const statements = parse(rulesInput, undefined) as AST; | ||
|
||
if (!Array.isArray(statements)) { | ||
throw new Error('Rules must be an array of statements'); | ||
} | ||
|
||
const changedFiles = await getChangedFiles(); | ||
log(`Changed Files: ${changedFiles.join('\n')}`); | ||
if (changedFilesOutputFile) { | ||
await writeChangedFiles(changedFilesOutputFile, changedFiles); | ||
} | ||
|
||
const { changes } = evaluateStatementsForChanges(statements, changedFiles); | ||
for (const [key, value] of Object.entries(changes)) { | ||
affectedChanges[key] = value; | ||
} | ||
|
||
const allFiles = await allGitFiles(); | ||
log(`All Git Files: ${allFiles.join('\n')}`); | ||
const commitSha = await evaluateStatementsForHashes(statements, allFiles); | ||
|
||
for (const statement of statements) { | ||
if (statement.type !== 'STATEMENT') continue; | ||
|
||
const { key } = statement; | ||
if (key.path) { | ||
affectedShas[key.name] = commitSha[key.name]; | ||
|
||
const imageName = getImageName(key.name, commitSha[key.name], truncateSha1Size, imageTagRegistry, imageTagPrefix, imageTagSuffix, imageContext); | ||
affectedImageTags[key.name] = imageName; | ||
|
||
log(`Key: ${key.name}, Path: ${key.path}, Commit SHA: ${commitSha}, Image: ${imageName}`); | ||
} | ||
} | ||
} | ||
|
||
return { | ||
shas: affectedShas, | ||
changes: affectedChanges, | ||
recommended_imagetags: affectedImageTags, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// node dist/apps/affected/cli/main.cli.js calculate --rules-file ./.github/affected.rules --verbose | ||
// node dist/apps/affected/cli/main.cli.js calculate --rules-file ./.github/affected.rules | ||
import yargs from 'yargs'; | ||
import { hideBin } from 'yargs/helpers'; | ||
import { processRules, getRules } from './common'; | ||
|
||
import * as packageJson from '../../../package.json'; | ||
|
||
export const log = (verbose: boolean, message: string) => { | ||
if (verbose) { | ||
console.log(message); | ||
} | ||
}; | ||
|
||
yargs(hideBin(process.argv)) | ||
.scriptName("main.cli.js") // Optional: Set a custom script name for the help output | ||
.usage('$0 <command> [options]') | ||
.version(packageJson.version) | ||
.command( | ||
'calculate', | ||
'Calculate affected targets', | ||
(yargs) => { | ||
yargs | ||
.option('rules', { type: 'string', describe: 'Rules as a string', demandOption: false }) | ||
.option('rules-file', { type: 'string', describe: 'Path to rules file', demandOption: false }) | ||
.option('verbose', { type: 'boolean', default: false, describe: 'Verbose logging' }) | ||
.option('truncate-sha1-size', { type: 'number', default: 0, describe: 'SHA1 truncation size' }) | ||
.option('image-tag-prefix', { type: 'string', default: '', describe: 'Image tag prefix' }) | ||
.option('image-tag-suffix', { type: 'string', default: '', describe: 'Image tag suffix' }) | ||
.option('image-tag-registry', { type: 'string', default: '', describe: 'Image tag registry' }) | ||
.option('changed-files-output-file', { type: 'string', describe: 'Path to write changed files', demandOption: false }); | ||
}, | ||
async (argv) => { | ||
try { | ||
const rules = getRules(argv.rules as string, argv['rules-file'] as string); | ||
const affectedOutput = await processRules( | ||
log.bind(null, argv.verbose as boolean), | ||
rules, | ||
argv['truncate-sha1-size'] as number, | ||
argv['image-tag-registry'] as string, | ||
argv['image-tag-prefix'] as string, | ||
argv['image-tag-suffix'] as string, | ||
argv['changed-files-output-file'] as string | undefined | ||
); | ||
console.info(`${JSON.stringify(affectedOutput, null, 2)}`); | ||
} catch (error) { | ||
console.error(error.message); | ||
process.exit(1); | ||
} | ||
} | ||
) | ||
.help() | ||
.argv; |
Oops, something went wrong.