UNPKG

@process-engine/ci_tools

Version:
218 lines (174 loc) 7.21 kB
import * as chalk from 'chalk'; import * as fs from 'fs'; import { existsSync } from 'fs'; import * as yargsParser from 'yargs-parser'; import { getGitBranch, getGitTagList, getGitTagsFromCommit, gitAdd, gitCommit, gitPush } from '../git/git'; import { getVersionTag } from '../versions/git_helpers'; import { getPackageVersion, setPackageVersion } from '../versions/package_version'; import { printMultiLineString } from '../cli/printMultiLineString'; import { sh } from '../cli/shell'; import { PACKAGE_MODE_DOTNET, PACKAGE_MODE_NODE, PACKAGE_MODE_PYTHON } from '../contracts/modes'; import { getCsprojAsObject, getCsprojPath } from '../versions/package_version/dotnet'; const COMMAND_NAME = 'copy-and-commit-version-for-subpackage'; const BADGE = `[${COMMAND_NAME}]\t`; const DEFAULT_MODE = 'node'; const DOC = ` Copies the version from the main package to a subpackage and commits the change. OPTIONS --mode sets the package mode [dotnet, node, python] (default: node) `; // DOC: see above export async function run(...args): Promise<boolean> { const argv = yargsParser(args, { alias: { help: ['h'] }, default: { mode: DEFAULT_MODE } }); const isDryRun = args.indexOf('--dry') !== -1; const isForced = process.env.CI_TOOLS_FORCE_PUBLISH === 'true' || args.indexOf('--force') !== -1; const mode = argv.mode; const subpackageLocation = getSubpackageLocationFromArgs(args); const mainPackageVersion = await getPackageVersion(mode); await printInfo(mode, mainPackageVersion, isDryRun, isForced); const subpackageLocationWithSlash = subpackageLocation.endsWith('/') ? subpackageLocation : `${subpackageLocation}/`; await abortIfRetryRun(mode, mainPackageVersion, subpackageLocationWithSlash); abortIfSubpackageLocationIsMissing(subpackageLocation); abortIfDryRun(mainPackageVersion, isDryRun, isForced); const cwd = process.cwd(); process.chdir(subpackageLocationWithSlash); await setPackageVersion(mode, mainPackageVersion); process.chdir(cwd); const branchName = getGitBranch(); const filename = getSubpackageFilename(mode, subpackageLocationWithSlash); gitAdd(`${subpackageLocationWithSlash}${filename}`); sh('git status'); const subpackageName = await getSubpackageName(mode, subpackageLocationWithSlash); gitCommit(`Update ${subpackageName} version to v${mainPackageVersion}\n\n[skip ci]`); gitPush('origin', branchName); return true; } export function getShortDoc(): string { return DOC.trim().split('\n')[0]; } export function printHelp(): void { console.log(`Usage: ci_tools ${COMMAND_NAME} <subpackageLocation> [--dry] [--force] [--mode <MODE>]`); console.log(''); console.log(DOC.trim()); } async function abortIfRetryRun(mode: string, mainPackageVersion: string, subpackageLocation: string): Promise<void> { const subpackageVersion = await getSubpackageVersion(mode, subpackageLocation); if (subpackageVersion === mainPackageVersion) { console.error(chalk.yellow(`${BADGE}Subpackage version is already "${mainPackageVersion}".`)); console.error(chalk.yellowBright(`${BADGE}Nothing to do here, since this is the current package version!`)); process.exit(0); } } async function getSubpackageVersion(mode: string, subpackageLocation: string): Promise<string> { const cwd = process.cwd(); process.chdir(subpackageLocation); const subpackageVersion = await getPackageVersion(mode); process.chdir(cwd); return subpackageVersion; } async function getSubpackageName(mode: string, subpackageLocation: string): Promise<string> { const subpackage = await getSubpackage(mode, subpackageLocation); switch (mode) { case PACKAGE_MODE_DOTNET: const propertyGroup = subpackage?.Project?.PropertyGroup; const name = Array.isArray(propertyGroup) ? propertyGroup[0]?.Product[0] : null; if (name == null) { return subpackageLocation; } return name; case PACKAGE_MODE_NODE: return subpackage.name; case PACKAGE_MODE_PYTHON: return subpackageLocation; default: break; } } async function getSubpackage(mode: string, subpackageLocation: string): Promise<any> { switch (mode) { case PACKAGE_MODE_DOTNET: return getSubpackageDotnet(subpackageLocation); case PACKAGE_MODE_NODE: return getSubpackageNode(subpackageLocation); case PACKAGE_MODE_PYTHON: return null; default: throw new Error(`Unknown value for \`mode\`: ${mode}`); } } function getSubpackageNode(subpackageLocation: string): any { const rawdata = fs.readFileSync(`${subpackageLocation}package.json`).toString(); const packageJson = JSON.parse(rawdata); return packageJson; } async function getSubpackageDotnet(subpackageLocation: string): Promise<any> { const cwd = process.cwd(); process.chdir(subpackageLocation); const filename = getCsprojPath(); const json = await getCsprojAsObject(filename); process.chdir(cwd); if (json == null) { throw new Error(`Could not convert csproj to JSON: ${filename}`); } return json; } function getSubpackageFilename(mode: string, subpackageLocation: string): string { switch (mode) { case PACKAGE_MODE_DOTNET: const cwd = process.cwd(); process.chdir(subpackageLocation); const filename = getCsprojPath(); process.chdir(cwd); return filename; case PACKAGE_MODE_NODE: return 'package.json'; case PACKAGE_MODE_PYTHON: return 'setup.py'; default: break; } } function getSubpackageLocationFromArgs(args): string | undefined { for (const arg of args) { console.log(arg); console.log(existsSync(arg)); if (existsSync(arg)) { return arg; } } return undefined; } function abortIfSubpackageLocationIsMissing(subpackageLocation): void { if (subpackageLocation == null) { console.error(chalk.red(`${BADGE}Can not proceed since the subpackage location is missing.`)); process.exit(1); } } function abortIfDryRun(nextVersion: string, isDryRun: boolean, isForced: boolean): void { if (isDryRun) { console.log(chalk.yellow(`${BADGE}I would write version ${nextVersion} to package.json.`)); console.log(chalk.yellow(`${BADGE}Aborting due to --dry.`)); if (isForced) { console.error(chalk.yellow(`${BADGE}Even though --force was provided, --dry takes precedence.`)); } process.exit(1); } } async function printInfo(mode: string, nextVersion: string, isDryRun: boolean, isForced: boolean): Promise<void> { const packageVersion = await getPackageVersion(mode); const packageVersionTag = getVersionTag(packageVersion); const branchName = getGitBranch(); const gitTagList = getGitTagList(); console.log(`${BADGE}isDryRun:`, isDryRun); console.log(`${BADGE}isForced:`, isForced); console.log(''); console.log(`${BADGE}packageVersion:`, packageVersion); console.log(`${BADGE}packageVersionTag:`, packageVersionTag); console.log(`${BADGE}branchName:`, branchName); console.log(`${BADGE}gitTagList:`); printMultiLineString(gitTagList); console.log(`${BADGE}tagsForHEAD:`); printMultiLineString(getGitTagsFromCommit('HEAD')); console.log(`${BADGE}nextVersionTag:`, getVersionTag(nextVersion)); console.log(''); }