Package publishing automates the process of releasing packages to npm registries with support for 2FA, custom tags, git tagging, and multi-package coordination.
The primary function for publishing packages to npm and creating git tags.
/**
* Publishes packages to npm registry and creates git tags
* @param cwd - Working directory path
* @param options.otp - One-time password for 2FA authentication
* @param options.tag - Custom npm dist-tag (defaults to "latest")
* @param options.gitTag - Whether to create git tags (defaults to true)
* @param config - Changesets configuration object
*/
function publish(
cwd: string,
options: {otp?: string, tag?: string, gitTag?: boolean},
config: Config
): Promise<void>;Usage Examples:
import { run } from "@changesets/cli";
// Standard publishing
await run(["publish"], {}, cwd);
// Publishing with 2FA token
await run(["publish"], { otp: "123456" }, cwd);
// Publishing with custom tag
await run(["publish"], { tag: "beta" }, cwd);
// Publishing without git tags
await run(["publish"], { gitTag: false }, cwd);Lower-level function for publishing individual packages with detailed control.
/**
* Core package publishing logic for multiple packages
* @param options.packages - Array of packages to publish
* @param options.access - Package access level (public or restricted)
* @param options.otp - One-time password for 2FA
* @param options.preState - Prerelease state for coordinated prereleases
* @param options.tag - Custom npm dist-tag
* @returns Array of publish results with success/failure status
*/
function publishPackages(options: {
packages: Package[],
access: AccessType,
otp?: string,
preState: PreState | undefined,
tag?: string
}): Promise<PublishedResult[]>;Usage Examples:
import publishPackages from "@changesets/cli/src/commands/publish/publishPackages";
const results = await publishPackages({
packages: packagesToPublish,
access: "public",
otp: process.env.NPM_OTP,
preState: undefined,
tag: "latest"
});
// Check results
results.forEach(result => {
if (result.published) {
console.log(`✓ Published ${result.name}@${result.newVersion}`);
} else {
console.log(`✗ Failed to publish ${result.name}`);
}
});Utilities for handling npm registry configuration and authentication.
/**
* Determines the correct npm registry for a package
* @param packageJson - Package.json object (optional)
* @returns Registry information including scope and URL
*/
function getCorrectRegistry(packageJson?: PackageJSON): RegistryInfo;
/**
* Checks if 2FA token is required for publishing
* @returns Promise resolving to boolean indicating 2FA requirement
*/
function getTokenIsRequired(): Promise<boolean>;
/**
* Gets package information from npm registry
* @param packageJson - Package.json object
* @returns Promise resolving to package registry information
*/
function getPackageInfo(packageJson: PackageJSON): Promise<any>;
/**
* Gets package info from registry, handling 404s gracefully
* @param packageJson - Package.json object
* @returns Promise resolving to publish status and package info
*/
function infoAllow404(
packageJson: PackageJSON
): Promise<{published: boolean, pkgInfo: any}>;Comprehensive 2FA support for secure publishing:
/**
* Gets 2FA token from user input or existing state
* @param twoFactorState - Current 2FA state object
* @returns Promise resolving to OTP token string
*/
function getOtpCode(twoFactorState: TwoFactorState): Promise<string>;
/**
* Publishes a single package to npm with 2FA support
* @param packageJson - Package.json object
* @param opts - Publishing options including registry and access
* @param twoFactorState - 2FA state for token management
* @returns Promise resolving to publish result
*/
function publish(
packageJson: PackageJSON,
opts: PublishOptions,
twoFactorState: TwoFactorState
): Promise<{published: boolean}>;2FA State Management:
interface TwoFactorState {
token: string | null;
isRequired: Promise<boolean>;
}Publishing automatically creates git tags for published versions:
// Default tag format: {packageName}@{version}
// Examples:
// @myorg/ui@1.2.0
// my-package@2.1.0Separate tag creation for packages that were published externally:
/**
* Creates git tags for published packages
* @param cwd - Working directory path
* @param config - Changesets configuration object
*/
function tag(cwd: string, config: Config): Promise<void>;Utility to find packages missing git tags after publishing:
/**
* Finds packages that are missing git tags
* @param packages - Array of package objects
* @param cwd - Working directory path
* @param tool - Package manager tool type
* @returns Promise resolving to array of packages needing tags
*/
function getUntaggedPackages(
packages: Package[],
cwd: string,
tool: Tool
): Promise<PublishedResult[]>;type AccessType = "restricted" | "public";
// Configuration options
interface Config {
access: "restricted" | "public"; // Default access level
privatePackages: {
version: boolean; // Whether to version private packages
tag: boolean; // Whether to tag private packages
};
}Individual packages can override global access settings:
{
"name": "@myorg/public-package",
"publishConfig": {
"access": "public"
}
}Support for publishing scoped packages to custom registries:
interface RegistryInfo {
scope?: string; // Package scope (e.g., "@myorg")
registry: string; // Registry URL
}// .npmrc configuration examples
registry=https://registry.npmjs.org/
@myorg:registry=https://npm.myorg.com/
//npm.myorg.com/:_authToken=${NPM_TOKEN}For packages in prerelease mode:
// Prerelease packages use the prerelease tag
// Example: 1.0.0-beta.1 published with tag "beta"
await publish(cwd, { tag: "beta" }, config);Snapshot releases are published with temporary versions:
// Snapshot versions like 0.0.0-20231201-abc1234
// Published with "snapshot" tag by default
await publish(cwd, { tag: "snapshot" }, config);The publishing system includes built-in retry logic for transient failures:
// Automatic retry for network-related failures
// Manual retry prompts for authentication issues
// Graceful degradation for partial publish failuresWhen publishing multiple packages, the system handles partial failures gracefully:
interface PublishedResult {
name: string;
newVersion: string;
published: boolean;
}
// Results indicate which packages succeeded/failed
// Failed packages can be retried individually
// Git tags are only created for successfully published packages{
"access": "restricted",
"privatePackages": {
"version": true,
"tag": false
}
}Integration with custom publish workflows:
{
"scripts": {
"changeset:publish": "changeset publish",
"changeset:publish:beta": "changeset publish --tag beta",
"changeset:publish:dry": "changeset publish --dry-run"
}
}interface PublishOptions {
registry?: string;
tag?: string;
access?: AccessType;
dryRun?: boolean;
}
interface PublishedResult {
name: string;
newVersion: string;
published: boolean;
}
type Tool = "yarn" | "npm" | "pnpm";
interface PreState {
mode: "pre";
tag: string;
initialVersions: Record<string, string>;
changesets: string[];
}