Skip to content

Commit 86664c4

Browse files
committed
build: support auto release type in publish script
--- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent f9db7b8 commit 86664c4

1 file changed

Lines changed: 98 additions & 2 deletions

File tree

lib/node_modules/@stdlib/_tools/scripts/publish_packages.js

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ var readFileSync = require( '@stdlib/fs/read-file' ).sync;
4040
var readJSON = require( '@stdlib/fs/read-json' ).sync;
4141
var existsSync = require( '@stdlib/fs/exists' ).sync;
4242
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
43+
var objectKeys = require( '@stdlib/utils/keys' );
4344
var contains = require( '@stdlib/assert/contains' );
4445
var memoize = require( '@stdlib/utils/memoize' );
4546
var repeat = require( '@stdlib/string/repeat' );
@@ -59,6 +60,8 @@ var namespaceDeps = require( '@stdlib/_tools/pkgs/namespace-deps' );
5960
var depList = require( '@stdlib/_tools/pkgs/dep-list' );
6061
var name2standalone = require( '@stdlib/_tools/pkgs/name2standalone' );
6162
var generateChangelog = require( '@stdlib/_tools/changelog/generate' );
63+
var recommendVersionBump = require( '@stdlib/_tools/changelog/recommend-version-bump' );
64+
var parseCommits = require( '@stdlib/_tools/changelog/parse-commits' );
6265
var toposort = require( '@stdlib/_tools/pkgs/toposort' ).sync;
6366
var ENV = require( '@stdlib/process/env' );
6467

@@ -345,6 +348,88 @@ var memoizedNPMversionForDevDeps = memoize( npmVersion );
345348

346349
// FUNCTIONS //
347350

351+
/**
352+
* Returns the date of the latest npm release for a package.
353+
*
354+
* @private
355+
* @param {string} pkg - package name
356+
* @returns {(string|null)} ISO date string or null
357+
*/
358+
function getLatestReleaseDate( pkg ) {
359+
var latestDate;
360+
var versions;
361+
var command;
362+
var version;
363+
var result;
364+
var date;
365+
var map;
366+
var i;
367+
368+
command = 'npm view ' + pkg + ' time --json';
369+
try {
370+
result = shell( command ).toString();
371+
map = JSON.parse( result );
372+
latestDate = null;
373+
versions = objectKeys( map );
374+
for ( i = 0; i < versions.length; i++ ) {
375+
version = versions[ i ];
376+
if (
377+
version !== 'created' &&
378+
version !== 'modified' &&
379+
version !== 'unpublished' &&
380+
semver.valid( version ) &&
381+
!semver.prerelease( version )
382+
) {
383+
date = new Date( map[ version ] );
384+
if ( !latestDate || date > latestDate ) {
385+
latestDate = date;
386+
}
387+
}
388+
}
389+
return ( latestDate ) ? latestDate.toISOString() : null;
390+
} catch ( error ) {
391+
debug( 'Encountered an error when attempting to retrieve release dates for package `%s`: %s', pkg, error.message );
392+
return null;
393+
}
394+
}
395+
396+
/**
397+
* Determines the release type automatically based on commits since the last release.
398+
*
399+
* @private
400+
* @param {string} pkg - package name (without @stdlib/ prefix)
401+
* @returns {(string|null)} release type (`minor`, `patch`) or null if no release needed
402+
*/
403+
function determineAutoReleaseType( pkg ) {
404+
var latestReleaseDate;
405+
var standalonePkg;
406+
var commitOpts;
407+
var commits;
408+
var bump;
409+
410+
standalonePkg = name2standalone( '@stdlib/' + pkg );
411+
latestReleaseDate = getLatestReleaseDate( standalonePkg );
412+
413+
commitOpts = {
414+
'dir': join( mainDir, 'lib/node_modules', '@stdlib', pkg )
415+
};
416+
if ( latestReleaseDate ) {
417+
commitOpts.flags = {
418+
'after': latestReleaseDate
419+
};
420+
}
421+
commits = parseCommits( commitOpts );
422+
423+
// Determine the recommended version bump:
424+
bump = recommendVersionBump( commits );
425+
426+
// Cap major bumps to minor (we don't want to increase major release line for now):
427+
if ( bump === 'major' ) {
428+
bump = 'minor';
429+
}
430+
return bump;
431+
}
432+
348433
/**
349434
* Returns a cron schedule for a given package.
350435
*
@@ -695,7 +780,18 @@ function publish( pkg, clbk ) {
695780
return invokeCallback( null, 'skipped' );
696781
}
697782

698-
if ( flags[ 'release-type' ] ) {
783+
if ( flags[ 'release-type' ] === 'auto' ) {
784+
// Case: auto-determine release type based on commits...
785+
releaseType = determineAutoReleaseType( pkg );
786+
if ( releaseType ) {
787+
changelog = generateChangelog( '@stdlib/'+pkg, {
788+
'releaseType': releaseType
789+
});
790+
} else {
791+
// No release needed, generate changelog without release type...
792+
changelog = generateChangelog( '@stdlib/'+pkg );
793+
}
794+
} else if ( flags[ 'release-type' ] ) {
699795
// Case: release type specified, so we generate a changelog for the specified release type...
700796
changelog = generateChangelog( '@stdlib/'+pkg, {
701797
'releaseType': flags[ 'release-type' ]
@@ -1087,7 +1183,7 @@ function publish( pkg, clbk ) {
10871183

10881184
// Write the current date to the `.keepalive` file...
10891185
if ( flags[ 'keep-alive' ] ) {
1090-
fs.writeFileSync( join( dist, '.github', '.keepalive' ), new Date().toISOString() + '\n' );
1186+
fs.writeFileSync( join( dist, '.github', '.keepalive' ), new Date().toISOString() + '\n' ); // eslint-disable-line no-restricted-syntax
10911187
}
10921188

10931189
fs.copyFileSync( join( __dirname, 'templates', 'CODE_OF_CONDUCT.md.txt' ), join( dist, 'CODE_OF_CONDUCT.md' ) );

0 commit comments

Comments
 (0)