Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 34 additions & 15 deletions src/targets/npm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
BaseArtifactProvider,
RemoteArtifact,
} from '../artifact_providers/base';
import { withTempFile } from '../utils/files';
import { writeFileSync } from 'fs';

const logger = loggerRaw.withScope('[npm]');

Expand All @@ -24,6 +26,8 @@ export const YARN_BIN = process.env.YARN_BIN || 'yarn';
const NPM_MIN_MAJOR = 5;
const NPM_MIN_MINOR = 6;

const NPM_TOKEN_ENV_VAR = 'NPM_TOKEN';

/** A regular expression used to find the package tarball */
const DEFAULT_PACKAGE_REGEX = /^.*\d\.\d.*\.tgz$/;

Expand All @@ -43,6 +47,8 @@ export interface NpmTargetOptions extends TargetConfig {
useOtp?: boolean;
/** Do we use Yarn instead of NPM? */
useYarn: boolean;
/** Value of NPM_TOKEN so we can pass it to npm executable */
token: string;
}

/** Options for running the NPM publish command */
Expand Down Expand Up @@ -125,8 +131,14 @@ export class NpmTarget extends BaseTarget {
* Extracts NPM target options from the raw configuration
*/
protected getNpmConfig(): NpmTargetOptions {
const token = process.env.NPM_TOKEN;
if (!token) {
throw new Error('NPM target: NPM_TOKEN not found in the environment');
}

const npmConfig: NpmTargetOptions = {
useYarn: !!process.env.USE_YARN || !hasExecutable(NPM_BIN),
token,
};
if (this.config.access) {
if (Object.values(NpmPackageAccess).includes(this.config.access)) {
Expand Down Expand Up @@ -180,21 +192,28 @@ export class NpmTarget extends BaseTarget {
args.push('--tag=next');
}

// Pass OTP if configured
const spawnOptions: SpawnOptions = {};
if (options.otp) {
spawnOptions.env = {
...process.env,
NPM_CONFIG_OTP: options.otp,
};
}

// The path has to be pushed always as the last arg
args.push(path);

// Disable output buffering because NPM/Yarn can ask us for one-time passwords
return spawnProcess(bin, args, spawnOptions, {
showStdout: true,
return withTempFile(filePath => {
// Pass OTP if configured
const spawnOptions: SpawnOptions = {};
spawnOptions.env = { ...process.env };
if (options.otp) {
spawnOptions.env.NPM_CONFIG_OTP = options.otp;
}
spawnOptions.env[NPM_TOKEN_ENV_VAR] = this.npmConfig.token;
// NOTE(byk): Use npm_config_userconfig instead of --userconfig for yarn compat
spawnOptions.env.npm_config_userconfig = filePath;
writeFileSync(
filePath,
`//registry.npmjs.org/:_authToken=\${${NPM_TOKEN_ENV_VAR}}`
);

// The path has to be pushed always as the last arg
args.push(path);

// Disable output buffering because NPM/Yarn can ask us for one-time passwords
return spawnProcess(bin, args, spawnOptions, {
showStdout: true,
});
});
}

Expand Down