diff --git a/npm/ng-packs/scripts/package.json b/npm/ng-packs/scripts/package.json index 3984a00b14..b0961239bb 100644 --- a/npm/ng-packs/scripts/package.json +++ b/npm/ng-packs/scripts/package.json @@ -17,7 +17,8 @@ "execa": "^2.0.3", "fs-extra": "^8.1.0", "glob": "^7.1.6", - "prompt-confirm": "^2.0.4" + "prompt-confirm": "^2.0.4", + "semver": "^7.3.5" }, "devDependencies": { "@types/fs-extra": "^8.0.1", diff --git a/npm/ng-packs/scripts/publish.ts b/npm/ng-packs/scripts/publish.ts index d54d177261..2ad098236c 100644 --- a/npm/ng-packs/scripts/publish.ts +++ b/npm/ng-packs/scripts/publish.ts @@ -1,7 +1,8 @@ +import program from 'commander'; import execa from 'execa'; import fse from 'fs-extra'; -import program from 'commander'; import replaceWithPreview from './replace-with-preview'; +const semverParse = require('semver/functions/parse'); program .option( @@ -10,14 +11,16 @@ program ) .option('-r, --registry ', 'target npm server registry') .option('-p, --preview', 'publishes with preview tag') - .option('-r, --rc', 'publishes with next tag') - .option('-g, --skipGit', 'skips git push'); + .option('-sg, --skipGit', 'skips git push') + .option('-sv, --skipVersionValidation', 'skips version validation'); program.parse(process.argv); (async () => { const versions = ['major', 'minor', 'patch', 'premajor', 'preminor', 'prepatch', 'prerelease']; + const oldVersion = fse.readJSONSync('../lerna.version.json').version; + if (!program.nextVersion) { console.error('Please provide a version with --nextVersion attribute'); process.exit(1); @@ -26,41 +29,43 @@ program.parse(process.argv); const registry = program.registry || 'https://registry.npmjs.org'; try { - await fse.remove('../dist'); - - await execa('yarn', ['install', '--ignore-scripts'], { stdout: 'inherit', cwd: '../' }); - - await fse.rename('../lerna.version.json', '../lerna.json'); - - await execa( - 'yarn', - [ - 'lerna', - 'version', - program.nextVersion, - '--yes', - '--no-commit-hooks', - '--skip-git', - '--force-publish', - ], - { stdout: 'inherit', cwd: '../' }, - ); - - await fse.rename('../lerna.json', '../lerna.version.json'); - - await execa('yarn', ['replace-with-tilde']); + await fse.remove('../dist/packages'); + + await execa('yarn', ['install'], { stdout: 'inherit', cwd: '../' }); + + await updateVersion(program.nextVersion); + + if (!program.skipVersionValidation) { + await execa( + 'yarn', + [ + 'validate-versions', + '--compareVersion', + program.nextVersion, + '--path', + '../ng-packs/packages', + ], + { stdout: 'inherit', cwd: '../../scripts' }, + ); + } if (program.preview) await replaceWithPreview(program.nextVersion); await execa('yarn', ['build', '--noInstall', '--skipNgcc'], { stdout: 'inherit' }); - await execa('yarn', ['build:schematics'], { stdout: 'inherit' }); + } catch (error) { + console.error(error.stderr); + console.error('\n\nAn error has occurred! Rolling back the changed package versions.'); + await updateVersion(oldVersion); + process.exit(1); + } + try { await fse.rename('../lerna.publish.json', '../lerna.json'); let tag: string; if (program.preview) tag = 'preview'; - if (program.rc) tag = 'next'; + else if (semverParse(program.nextVersion).prerelease?.length) tag = 'next'; await execa( 'yarn', @@ -72,7 +77,14 @@ program.parse(process.argv); ); await fse.rename('../lerna.json', '../lerna.publish.json'); + } catch (error) { + console.error(error.stderr); + console.error('\n\nAn error has occurred while publishing to the NPM!'); + await fse.rename('../lerna.json', '../lerna.publish.json'); + process.exit(1); + } + try { if (!program.preview && !program.skipGit) { await execa('git', ['add', '../packages/*', '../package.json', '../lerna.version.json'], { stdout: 'inherit', @@ -88,3 +100,17 @@ program.parse(process.argv); process.exit(0); })(); + +async function updateVersion(version: string) { + await fse.rename('../lerna.version.json', '../lerna.json'); + + await execa( + 'yarn', + ['lerna', 'version', version, '--yes', '--no-commit-hooks', '--skip-git', '--force-publish'], + { stdout: 'inherit', cwd: '../' }, + ); + + await fse.rename('../lerna.json', '../lerna.version.json'); + + await execa('yarn', ['replace-with-tilde']); +} diff --git a/npm/package-update-script.js b/npm/package-update-script.js index 58e24db554..b0938d3774 100644 --- a/npm/package-update-script.js +++ b/npm/package-update-script.js @@ -1,11 +1,13 @@ + + const glob = require('glob'); var path = require('path'); const childProcess = require('child_process'); const { program } = require('commander'); program.version('0.0.1'); -program.option('-r, --rc', 'whether version is rc'); -program.option('-rg, --registry ', 'target npm server registry') +program.option('-pr, --prerelase', 'whether version is prerelase'); +program.option('-rg, --registry ', 'target npm server registry'); program.parse(process.argv); const packages = (process.argv[3] || 'abp').split(',').join('|'); @@ -15,7 +17,7 @@ const check = (pkgJsonPath) => { return childProcess .execSync( `ncu "/^@(${packages}).*$/" --packageFile ${pkgJsonPath} -u${ - program.rc ? ' --target greatest' : '' + program.prerelase ? ' --target newest' : '' }${program.registry ? ` --registry ${program.registry}` : ''}` ) .toString(); @@ -40,4 +42,4 @@ glob(folder + '/**/package.json', {}, (er, files) => { console.log(check(file)); }); -}); +}); \ No newline at end of file diff --git a/npm/package.json b/npm/package.json index 724b0f7be1..2838e8eac0 100644 --- a/npm/package.json +++ b/npm/package.json @@ -16,6 +16,8 @@ "dependencies": { "commander": "^6.0.0", "execa": "^3.4.0", - "fs-extra": "^8.1.0" + "fast-glob": "^3.2.7", + "fs-extra": "^8.1.0", + "semver": "^7.3.5" } } diff --git a/npm/publish-mvc.ps1 b/npm/publish-mvc.ps1 new file mode 100644 index 0000000000..bba7b44bb7 --- /dev/null +++ b/npm/publish-mvc.ps1 @@ -0,0 +1,51 @@ +param( + [string]$Version, + [string]$Registry +) + +yarn install + +$NextVersion = $(node publish-utils.js --nextVersion) +$RootFolder = (Get-Item -Path "./" -Verbose).FullName + +if (-Not $Version) { + $Version = $NextVersion; +} + +if (-Not $Registry) { + $Registry = "https://registry.npmjs.org"; +} + +$PacksPublishCommand = "npm run lerna -- exec 'npm publish --registry $Registry'" + +$IsPrerelase = $(node publish-utils.js --prerelase --customVersion $Version) -eq "true"; + +if ($IsPrerelase) { + $PacksPublishCommand = $PacksPublishCommand.Substring(0, $PacksPublishCommand.Length - 1) + " --tag next'" +} + +$commands = ( + "npm run lerna -- version $Version --yes --no-commit-hooks --skip-git --force-publish", + "yarn replace-with-tilde", + "cd scripts", + "yarn install", + "yarn validate-versions --compareVersion $Version --path ../packs", + "cd ..", + $PacksPublishCommand +) + +foreach ($command in $commands) { + $timer = [System.Diagnostics.Stopwatch]::StartNew() + Write-Host $command + Invoke-Expression $command + if ($LASTEXITCODE -ne '0' -And $command -notlike '*cd *') { + Write-Host ("Process failed! " + $command) + Set-Location $RootFolder + exit $LASTEXITCODE + } + $timer.Stop() + $total = $timer.Elapsed + Write-Output "-------------------------" + Write-Output "$command command took $total (Hours:Minutes:Seconds.Milliseconds)" + Write-Output "-------------------------" +} \ No newline at end of file diff --git a/npm/publish.ps1 b/npm/publish-ng.ps1 similarity index 67% rename from npm/publish.ps1 rename to npm/publish-ng.ps1 index 486c6c6f4e..0ca666ae68 100644 --- a/npm/publish.ps1 +++ b/npm/publish-ng.ps1 @@ -3,7 +3,7 @@ param( [string]$Registry ) -npm install +yarn install $NextVersion = $(node publish-utils.js --nextVersion) $RootFolder = (Get-Item -Path "./" -Verbose).FullName @@ -17,32 +17,23 @@ if (-Not $Registry) { } $NgPacksPublishCommand = "npm run publish-packages -- --nextVersion $Version --skipGit --registry $Registry" -$PacksPublishCommand = "npm run lerna -- exec 'npm publish --registry $Registry'" $UpdateGulpCommand = "npm run update-gulp" $UpdateNgPacksCommand = "yarn update --registry $Registry" -$IsRc = $(node publish-utils.js --rc --customVersion $Version) -eq "true"; +$IsPrerelase = $(node publish-utils.js --prerelase --customVersion $Version) -eq "true"; - - -if ($IsRc) { - $NgPacksPublishCommand += " --rc" - $UpdateGulpCommand += " -- --rc" - $PacksPublishCommand = $PacksPublishCommand.Substring(0, $PacksPublishCommand.Length - 1) + " --tag next'" - $UpdateNgPacksCommand += " --rc" +if ($IsPrerelase) { + $UpdateGulpCommand += " -- --prerelase" + $UpdateNgPacksCommand += " --prerelase" } $commands = ( - "npm run lerna -- version $Version --yes --no-commit-hooks --skip-git --force-publish", - "npm run replace-with-tilde", - $PacksPublishCommand, $UpdateNgPacksCommand, "cd ng-packs\scripts", - "npm install", + "yarn install", $NgPacksPublishCommand, "cd ../../", "cd scripts", - "yarn", "yarn remove-lock-files", "cd ..", $UpdateGulpCommand diff --git a/npm/publish-utils.js b/npm/publish-utils.js index 395045c374..a88f3ed238 100644 --- a/npm/publish-utils.js +++ b/npm/publish-utils.js @@ -1,16 +1,18 @@ const { program } = require('commander'); const fse = require('fs-extra'); +const semverParse = require('semver/functions/parse'); program.version('0.0.1'); program.option('-n, --nextVersion', 'version in common.props'); -program.option('-r, --rc', 'whether version is rc'); +program.option('-pr, --prerelase', 'whether version is prerelase'); program.option('-cv, --customVersion ', 'set exact version'); program.parse(process.argv); if (program.nextVersion) console.log(getVersion()); -if (program.rc) console.log(getVersion().includes('rc')); +if (program.prerelase) + console.log(!!semverParse(getVersion()).prerelease?.length); function getVersion() { if (program.customVersion) return program.customVersion; @@ -20,4 +22,4 @@ function getVersion() { const first = commonProps.indexOf(versionTag) + versionTag.length; const last = commonProps.indexOf(versionEndTag); return commonProps.substring(first, last); -} +} \ No newline at end of file diff --git a/npm/replace-with-tilde.js b/npm/replace-with-tilde.js index 34438f4f5f..30ace73f13 100644 --- a/npm/replace-with-tilde.js +++ b/npm/replace-with-tilde.js @@ -1,5 +1,5 @@ -const glob = require('glob'); -const fse = require('fs-extra'); +const glob = require("glob"); +const fse = require("fs-extra"); function replace(filePath) { const pkg = fse.readJsonSync(filePath); @@ -9,20 +9,20 @@ function replace(filePath) { if (!dependencies) return; Object.keys(dependencies).forEach((key) => { - if (key.includes('@abp/') && key !== '@abp/utils') { - dependencies[key] = dependencies[key].replace('^', '~'); + if (key.includes("@abp/")) { + dependencies[key] = dependencies[key].replace("^", "~"); } }); fse.writeJsonSync(filePath, { ...pkg, dependencies }, { spaces: 2 }); } -glob('./packs/**/package.json', {}, (er, files) => { +glob("./packs/**/package.json", {}, (er, files) => { files.forEach((path) => { - if (path.includes('node_modules')) { + if (path.includes("node_modules")) { return; } replace(path); }); -}); +}); \ No newline at end of file diff --git a/npm/scripts/package.json b/npm/scripts/package.json index 89e935db21..c8d20924f8 100644 --- a/npm/scripts/package.json +++ b/npm/scripts/package.json @@ -3,12 +3,14 @@ "version": "1.0.0", "description": "", "scripts": { - "remove-lock-files": "ts-node -r tsconfig-paths/register remove-lock-files.ts" + "remove-lock-files": "ts-node -r tsconfig-paths/register remove-lock-files.ts", + "validate-versions": "ts-node -r tsconfig-paths/register validate-versions.ts" }, "dependencies": { + "axios": "^0.24.0", "chalk": "^4.1.0", - "commander": "^6.1.0", - "execa": "^4.0.3", + "commander": "^8.3.0", + "execa": "^5.1.1", "fs-extra": "^9.0.1", "glob": "^7.1.6", "npm-check-updates": "^9.0.1", diff --git a/npm/scripts/validate-versions.ts b/npm/scripts/validate-versions.ts new file mode 100644 index 0000000000..98f636351a --- /dev/null +++ b/npm/scripts/validate-versions.ts @@ -0,0 +1,82 @@ +import { program } from 'commander'; +import fse from 'fs-extra'; +import * as path from 'path'; +import { log } from './utils/log'; + +let excludedPackages = []; + +(async () => { + initCommander(); + await compare(); +})(); + +function initCommander() { + program.requiredOption( + '-v, --compareVersion ', + 'version to compare' + ); + program.requiredOption('-p, --path ', 'NPM packages folder path'); + program.option( + '-ep, --excludedPackages ', + 'Packages that will not be checked. Can be passed with separeted comma (like @abp/utils,@abp/core)', + '' + ); + program.parse(process.argv); + + excludedPackages = program.opts().excludedPackages.split(','); +} + +async function compare() { + let { compareVersion, path: packagesPath } = program.opts(); + packagesPath = path.resolve(packagesPath); + const packageFolders = await fse.readdir(packagesPath); + + for (let i = 0; i < packageFolders.length; i++) { + const folder = packageFolders[i]; + const pkgJsonPath = `${packagesPath}/${folder}/package.json`; + let pkgJson; + try { + pkgJson = await fse.readJSON(pkgJsonPath); + } catch (error) {} + + if ( + !excludedPackages.includes(pkgJson.name) && + pkgJson.version !== compareVersion + ) { + throwError(pkgJsonPath, pkgJson.name); + } + + const { dependencies, peerDependencies } = pkgJson; + if (dependencies) await compareDependencies(dependencies, pkgJsonPath); + // if (peerDependencies) { // TODO: update peerDependencies while updating version + // await compareDependencies(peerDependencies, pkgJsonPath); + // } + } +} + +async function compareDependencies( + dependencies: Record, + filePath: string +) { + const { compareVersion } = program.opts(); + const entries = Object.entries(dependencies); + + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + + if ( + !excludedPackages.includes(entry[0]) && + entry[0].match(/@(abp|volo)/)?.length && + entry[1] !== `~${compareVersion}` + ) { + throwError(filePath, entry[0], `~${compareVersion}`); + } + } +} + +function throwError(filePath: string, pkg: string, version?: string) { + const { compareVersion } = program.opts(); + + log.error(`${filePath}: ${pkg} version is not ${version || compareVersion}`); + process.exit(1); +} diff --git a/npm/update-gulp.js b/npm/update-gulp.js index d6076978eb..67fddab942 100644 --- a/npm/update-gulp.js +++ b/npm/update-gulp.js @@ -1,4 +1,4 @@ -const glob = require('glob'); +const glob = require('fast-glob'); var path = require('path'); const childProcess = require('child_process'); const execa = require('execa'); @@ -6,7 +6,7 @@ const fse = require('fs-extra'); const { program } = require('commander'); program.version('0.0.1'); -program.option('-r, --rc', 'whether version is rc'); +program.option('-pr, --prerelase', 'whether version is prerelase'); program.parse(process.argv); const gulp = (folderPath) => { @@ -18,8 +18,9 @@ const gulp = (folderPath) => { } try { - execa.sync(`yarn`, ['install'], { cwd: folderPath, stdio: 'inherit' }); - execa.sync(`yarn`, ['gulp'], { cwd: folderPath, stdio: 'inherit' }); + fse.removeSync(`${folderPath}/wwwroot/libs`); + execa.sync('yarn', ['install'], { cwd: folderPath, stdio: 'inherit' }); + execa.sync('yarn', ['gulp'], { cwd: folderPath, stdio: 'inherit' }); } catch (error) { console.log('\x1b[31m', 'Error: ' + error.message); } @@ -30,7 +31,7 @@ const updatePackages = (pkgJsonPath) => { const result = childProcess .execSync( `ncu "/^@abp.*$/" --packageFile ${pkgJsonPath} -u${ - program.rc ? ' --target greatest' : '' + program.prerelase ? ' --target newest' : '' }` ) .toString(); @@ -40,8 +41,9 @@ const updatePackages = (pkgJsonPath) => { } }; -console.time(); -glob('../**/package.json', {}, (er, files) => { +(async () => { + console.time(); + let files = await glob('../**/package.json'); files = files.filter( (f) => f && @@ -53,7 +55,9 @@ glob('../**/package.json', {}, (er, files) => { files.forEach((file) => { updatePackages(file); - gulp(file.replace('package.json', '')); + const folderPath = file.replace('package.json', ''); + gulp(folderPath); }); + console.timeEnd(); -}); +})(); \ No newline at end of file