Skip to content

Commit

Permalink
[Breaking] drop node < 12
Browse files Browse the repository at this point in the history
node 0.8 can no longer connect to the registry, and this enables getting lots of security updates.

With prepublishOnly, this should also only be run in actual publishing, which should only be in a modern node
  • Loading branch information
ljharb committed Oct 13, 2021
1 parent 72dfebb commit 3a8d144
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 224 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
@@ -1,11 +1,12 @@
{
"root": true,

"extends": "@ljharb",
"extends": "@ljharb/eslint-config/node/latest",

"rules": {
"array-bracket-newline": [2, { "multiline": true, "minItems": 1 }],
"array-element-newline": [2, { "multiline": true, "minItems": 2 }],
"func-style": "off",
"max-lines-per-function": [2, 115],
"max-params": [2, 4],
"max-statements": [2, 20],
Expand Down
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: ljharb/actions/node/matrix@main
id: set-matrix
with:
preset: '>=4'
preset: '>=12'

latest:
needs: [matrix]
Expand Down Expand Up @@ -51,7 +51,7 @@ jobs:
- uses: codecov/codecov-action@v2

node:
name: 'node 4+'
name: 'node 12+'
needs: [latest, minors]
runs-on: ubuntu-latest
steps:
Expand Down
60 changes: 0 additions & 60 deletions .github/workflows/node-iojs.yml

This file was deleted.

69 changes: 0 additions & 69 deletions .github/workflows/node-zero.yml

This file was deleted.

16 changes: 9 additions & 7 deletions README.md
Expand Up @@ -12,15 +12,16 @@ Ensure that when you `npm publish`, the "latest" tag is only set for the truly l

## Usage

Add "safe-publish-latest" to your `package.json`'s "prepublish" script.
Add "safe-publish-latest" to your `package.json`'s "prepublish" script, and install `in-publish`.

It will only activate during an actual `npm publish` - it will silently do nothing during installs, and will error when run directly.

Example `package.json` excerpt with no other prepublish commands:
```json
{
"scripts": {
"prepublish": "safe-publish-latest"
"prepublishOnly": "safe-publish-latest",
"prepublish": "not-in-publish || npm run prepublishOnly"
}
}
```
Expand All @@ -29,7 +30,8 @@ Example `package.json` excerpt with another prepublish command:
```json
{
"scripts": {
"prepublish": "safe-publish-latest && npm run build"
"prepublishOnly": "safe-publish-latest && npm run build",
"prepublish": "not-in-publish || npm run prepublishOnly"
}
}
```
Expand All @@ -39,15 +41,15 @@ Example `package.json` excerpt with another prepublish command:
Simply clone the repo, `npm install`, and run `npm test`

[1]: https://npmjs.org/package/safe-publish-latest
[2]: http://versionbadg.es/ljharb/safe-publish-latest.svg
[2]: https://versionbadg.es/ljharb/safe-publish-latest.svg
[3]: https://travis-ci.org/ljharb/safe-publish-latest.svg
[4]: https://travis-ci.org/ljharb/safe-publish-latest
[5]: https://david-dm.org/ljharb/safe-publish-latest.svg
[6]: https://david-dm.org/ljharb/safe-publish-latest
[7]: https://david-dm.org/ljharb/safe-publish-latest/dev-status.svg
[8]: https://david-dm.org/ljharb/safe-publish-latest#info=devDependencies
[9]: https://nodei.co/npm/safe-publish-latest.png?downloads=true&stars=true
[license-image]: http://img.shields.io/npm/l/safe-publish-latest.svg
[license-image]: https://img.shields.io/npm/l/safe-publish-latest.svg
[license-url]: LICENSE
[downloads-image]: http://img.shields.io/npm/dm/safe-publish-latest.svg
[downloads-url]: http://npm-stat.com/charts.html?package=safe-publish-latest
[downloads-image]: https://img.shields.io/npm/dm/safe-publish-latest.svg
[downloads-url]: https://npm-stat.com/charts.html?package=safe-publish-latest
26 changes: 12 additions & 14 deletions bin/safe-publish-latest
Expand Up @@ -2,19 +2,19 @@

'use strict';

var options = require('yargs')
const options = require('yargs')
.boolean('force-in-publish')
.default('force-in-publish', false)
.describe('force-in-publish', 'force "in publish" check to pass')
.help().alias('help', 'h')
.version(require('../package.json').version).alias('version', 'v')
.help()
.version().alias('version', 'v')
.strict()
.wrap(null)
.argv;

// eslint-disable-next-line global-require
var inPublish = options['force-in-publish'] || require('in-publish').inPublish();
var inInstall = require('in-publish').inInstall();
const inPub = require('in-publish');
const inPublish = options['force-in-publish'] || inPub.inPublish();
const inInstall = inPub.inInstall();

if (!inInstall && !inPublish) {
console.warn('Detected non-install and non-publish: exiting.');
Expand All @@ -23,24 +23,22 @@ if (!inPublish) {
process.exit(0);
}

var path = require('path');
const path = require('path');

var pkg = require(path.join(process.cwd(), 'package.json'));
var name = pkg.name;
const { name, version } = require(path.join(process.cwd(), 'package.json'));
if (!name) {
console.error('Error: package name is required');
process.exit(1);
}

var version = pkg.version;
var semver = require('semver');
const semver = require('semver');
if (!semver.valid(version)) {
console.error('Error: package version "' + version + '" is invalid.');
console.error(`Error: package version "${version}" is invalid.`);
process.exit(2);
}

var getLatestError = require('../getLatestError');
getLatestError(name, version, options, function (errors, messages) {
const getLatestError = require('../getLatestError');
getLatestError(name, version, options, (errors, messages) => {
if (!errors) {
console.log([].concat(messages, 'Publish away!').join('\n'));
process.exit(0);
Expand Down
51 changes: 28 additions & 23 deletions getLatestError.js
@@ -1,16 +1,21 @@
'use strict';

var exec = require('child_process').exec;
var semver = require('semver');
var format = require('util').format;
var getTag = require('./getTag');
const { exec } = require('child_process');
const {
eq,
gtr,
maxSatisfying,
prerelease,
} = require('semver');
const { format } = require('util');
const getTag = require('./getTag');

var isPrerelease = function (v) {
return semver.prerelease(v) !== null;
};
var isNotPrerelease = function (v) {
function isPrerelease(v) {
return prerelease(v) !== null;
}
function isNotPrerelease(v) {
return !isPrerelease(v);
};
}

module.exports = function getLatestError(name, version, options, callback) {
if (process.env.PUBLISH_LATEST_DANGEROUSLY === 'true') {
Expand All @@ -20,49 +25,49 @@ module.exports = function getLatestError(name, version, options, callback) {
return callback(null, 'Non-latest dist-tag detected.');
}

return exec('npm info ' + name + ' versions --json --loglevel=info', function (err, json) {
return exec(`npm info ${name} versions --json --loglevel=info`, (err, json) => {
if (err) {
if ((/^npm ERR! code E404$/m).test(err)) {
return callback(null, 'v' + version + ' is the first version published.');
return callback(null, `v${version} is the first version published.`);
}
return callback([
'Error fetching package versions:',
err
err,
]);
}
var allVersions;
let allVersions;
try {
allVersions = [].concat(JSON.parse(json));
} catch (e) {
return callback([
'Error parsing JSON from npm',
e
e,
]);
}

var versions = allVersions.filter(isNotPrerelease);
const versions = allVersions.filter(isNotPrerelease);
if (versions.length === 0) {
return callback(null, 'No non-prerelease versions detected.');
}

var max = semver.maxSatisfying(versions, '*');
if (semver.eq(version, max)) {
const max = maxSatisfying(versions, '*');
if (eq(version, max)) {
return callback([
'Attempting to publish already-published version v' + version + '.'
`Attempting to publish already-published version v${version}.`,
]);
}

var greater = semver.gtr(version, versions.join('||'));
var prerelease = isPrerelease(version);
if (!greater || prerelease) {
var msg = prerelease
const greater = gtr(version, versions.join('||'));
const isPre = isPrerelease(version);
if (!greater || isPre) {
const msg = isPre
? format('Attempting to publish v%s as "latest", but it is a prerelease version.', version)
: format('Attempting to publish v%s as "latest", but it is not later than v%s.', version, max);
return callback([
msg,
'\nPossible Solutions:',
'\t1) Provide a dist-tag: `npm publish --tag=backport`, for example',
'\t2) Use the very dangerous override: `PUBLISH_LATEST_DANGEROUSLY=true npm publish`'
'\t2) Use the very dangerous override: `PUBLISH_LATEST_DANGEROUSLY=true npm publish`',
]);
}

Expand Down
8 changes: 4 additions & 4 deletions package.json
Expand Up @@ -44,20 +44,20 @@
],
"dependencies": {
"in-publish": "^2.0.1",
"semver": "^6.3.0",
"yargs": "^7.1.2"
"semver": "^7.3.5",
"yargs": "^17.2.1"
},
"devDependencies": {
"@ljharb/eslint-config": "^18.0.0",
"aud": "^1.1.5",
"eclint": "^2.8.1",
"eslint": "^7.32.0",
"mock-env": "^0.2.0",
"nyc": "^10.3.2",
"nyc": "^15.1.0",
"tape": "^5.3.1"
},
"engines": {
"node": ">= 0.10"
"node": ">= 12"
},
"greenkeeper": {
"ignore": [
Expand Down

0 comments on commit 3a8d144

Please sign in to comment.