Skip to content
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions .github/workflows/pr-merged-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ jobs:
- name: Run Release
if: steps.check_version.outputs.has_changes == 'true'
run: |
npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_AUTH_TOKEN }}
git tag --points-at ${{ github.event.head_commit.id }}
node common/scripts/install-run-rush.js release --commit ${{ github.event.head_commit.id }}
env:
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ jobs:
node common/scripts/install-run-rush.js install

- name: Run Release
run: node common/scripts/install-run-rush.js release --commit ${{ github.event.head_commit.id }}
run: |
npm config set //registry.npmjs.org/:_authToken ${{ secrets.NPM_AUTH_TOKEN }}
node common/scripts/install-run-rush.js release --commit ${{ github.event.head_commit.id }}
env:
NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,5 @@ sensitive_info_result.txt

.rollup.cache
lib

log
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@coze-arch/rush-publish-plugin",
"comment": "support registry priority configuration",
"type": "minor"
}
],
"packageName": "@coze-arch/rush-publish-plugin",
"email": "tecvan.fe@qq.com"
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ describe('publish action', () => {
false,
{
isReleaseMode: false,
registry: 'https://registry.npmjs.org',
registry: undefined,
},
);
expect(applyPublishManifest).toHaveBeenCalledWith(mockPublishManifests);
Expand Down Expand Up @@ -326,7 +326,7 @@ describe('publish action', () => {
});
expect(confirmForPublish).toHaveBeenCalledWith(mockPublishManifests, true, {
isReleaseMode: false,
registry: 'https://registry.npmjs.org',
registry: undefined,
});
});

Expand Down Expand Up @@ -416,7 +416,7 @@ describe('publish action', () => {
expect(pushToRemote).toHaveBeenCalled();
});

it('should use default registry when registry is not provided', async () => {
it('should use undefined registry when registry is not provided (use npm config)', async () => {
vi.mocked(generatePublishManifest).mockResolvedValue({
manifests: mockPublishManifests,
bumpPolicy: BumpType.BETA,
Expand All @@ -430,7 +430,7 @@ describe('publish action', () => {

expect(release).toHaveBeenCalledWith({
dryRun: false,
registry: 'https://registry.npmjs.org',
registry: undefined,
packages: expect.any(Array),
});
});
Expand Down Expand Up @@ -473,7 +473,7 @@ describe('publish action', () => {

expect(release).toHaveBeenCalledWith({
dryRun: true,
registry: 'https://registry.npmjs.org',
registry: undefined,
packages: expect.any(Array),
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,13 @@ describe('confirm', () => {
});
});

it('should show default registry when registry is not provided in release mode', async () => {
it('should show npm configured registry when registry is not provided in release mode', async () => {
await confirmForPublish(mockPublishManifests, false, {
isReleaseMode: true,
});

expect(logger.warn).toHaveBeenCalledWith(
expect.stringContaining('default registry'),
expect.stringContaining('npm configured registry'),
false,
);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) 2025 coze-dev
// SPDX-License-Identifier: MIT

import { describe, it, expect, vi, beforeEach } from 'vitest';
import type { RushConfigurationProject } from '@rushstack/rush-sdk';

import { resolveRegistry } from '../../src/utils/resolve-registry';

// Mock logger
vi.mock('@coze-arch/logger', () => ({
logger: {
info: vi.fn(),
},
}));

describe('resolveRegistry', () => {
let mockProject: RushConfigurationProject;

beforeEach(() => {
// 创建一个基础的 mock project
const baseMockProject: Partial<RushConfigurationProject> = {
packageName: '@test/package',
packageJson: {},
};
mockProject = baseMockProject as RushConfigurationProject;
});

it('should use CLI registry with highest priority', () => {
mockProject.packageJson = {
publishConfig: { registry: 'https://package.json.registry.com' },
};

const result = resolveRegistry(mockProject, 'https://cli.registry.com');

expect(result).toBe('https://cli.registry.com');
});

it('should use package.json publishConfig.registry when CLI is not provided', () => {
mockProject.packageJson = {
publishConfig: { registry: 'https://package.json.registry.com' },
};

const result = resolveRegistry(mockProject);

expect(result).toBe('https://package.json.registry.com');
});

it('should return undefined when no config is provided (use npm config)', () => {
mockProject.packageJson = {};

const result = resolveRegistry(mockProject);

expect(result).toBeUndefined();
});

it('should handle package.json without publishConfig', () => {
mockProject.packageJson = {
name: '@test/package',
version: '1.0.0',
};

const result = resolveRegistry(mockProject);

expect(result).toBeUndefined();
});

it('should handle empty publishConfig in package.json', () => {
mockProject.packageJson = {
publishConfig: {},
};

const result = resolveRegistry(mockProject);

expect(result).toBeUndefined();
});

it('should handle undefined CLI parameter explicitly', () => {
mockProject.packageJson = {};

const result = resolveRegistry(mockProject, undefined);

expect(result).toBeUndefined();
});

it('should prioritize CLI over package.json even with empty string', () => {
mockProject.packageJson = {
publishConfig: { registry: 'https://package.json.registry.com' },
};

const result = resolveRegistry(mockProject, '');

// Empty string is falsy, so should fall back to package.json
expect(result).toBe('https://package.json.registry.com');
});
});
14 changes: 9 additions & 5 deletions packages/rush-plugins/publish/src/action/publish/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { release } from '../release/action';
import { randomHash } from '../../utils/random';
import { ensureNotUncommittedChanges, isMainBranch } from '../../utils/git';
import { getRushConfiguration } from '../../utils/get-rush-config';
import { DEFAULT_NPM_REGISTRY } from '../../const';
import { generatePublishManifest } from './version';
import { BumpType, type PublishOptions } from './types';
import { pushToRemote } from './push-to-remote';
Expand All @@ -21,8 +20,10 @@ import { applyPublishManifest } from './apply-new-version';
// 2. beta: 本分支直接切换版本号,并发布
// 3. 正式版本:发起MR,MR 合入 main 后,触发发布

const SESSION_ID_LENGTH = 6;

export const publish = async (options: PublishOptions) => {
const sessionId = randomHash(6);
const sessionId = randomHash(SESSION_ID_LENGTH);
const rushConfiguration = getRushConfiguration();
const rushFolder = rushConfiguration.rushJsonFolder;
if (
Expand Down Expand Up @@ -70,7 +71,7 @@ export const publish = async (options: PublishOptions) => {
!!options.dryRun,
{
isReleaseMode: !!options.release,
registry: options.registry || DEFAULT_NPM_REGISTRY,
registry: options.registry,
},
);

Expand Down Expand Up @@ -106,13 +107,16 @@ export const publish = async (options: PublishOptions) => {
// Release 模式:直接发布
logger.info('Running in direct release mode...');
logger.info('Starting package release...');
const registry = options.registry || DEFAULT_NPM_REGISTRY;
// 将 PublishManifest[] 转换为 PackageToPublish[]
const packages = publishManifests.map(manifest => ({
packageName: manifest.project.packageName,
version: manifest.newVersion,
}));
await release({ dryRun: !!options.dryRun, registry, packages });
await release({
dryRun: !!options.dryRun,
registry: options.registry,
packages,
});
} else {
// 普通模式:创建并推送发布分支
await pushToRemote({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const confirmForPublish = async (
if (options?.isReleaseMode) {
logger.info('', false);
logger.warn(chalk.yellow.bold('⚠️ Release Mode Enabled:'), false);
const registryMsg = ` Packages will be published directly to: ${chalk.bold(options.registry || 'default registry')}`;
const registryMsg = ` Packages will be published directly to: ${chalk.bold(options.registry || 'npm configured registry')}`;
logger.warn(chalk.yellow(registryMsg), false);
}

Expand Down
5 changes: 2 additions & 3 deletions packages/rush-plugins/publish/src/action/publish/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { logger } from '@coze-arch/logger';

import { getCurrentOrigin } from '../../utils/git';
import { type InstallAction } from '../../types';
import { DEFAULT_BRANCH_PREFIX, DEFAULT_NPM_REGISTRY } from '../../const';
import { DEFAULT_BRANCH_PREFIX } from '../../const';
import { type PublishOptions } from './types';
import { GIT_REPO_URL_REGEX } from './const';
import { publish } from './action';
Expand Down Expand Up @@ -50,8 +50,7 @@ export const installAction: InstallAction = (program: Command) => {
)
.option(
'--registry <url>',
`NPM registry URL (default: ${DEFAULT_NPM_REGISTRY})`,
DEFAULT_NPM_REGISTRY,
'NPM registry URL (优先级: CLI参数 > package.json publishConfig.registry > npm config)',
)
.action(async (options: PublishOptions) => {
try {
Expand Down
2 changes: 1 addition & 1 deletion packages/rush-plugins/publish/src/action/publish/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface PublishOptions {
repoUrl: string; // Git 仓库 URL,例如:git@github.com:coze-dev/coze-js.git
branchPrefix?: string; // Git 分支名前缀,默认见 DEFAULT_BRANCH_PREFIX
release?: boolean; // 是否直接发布(仅支持 alpha/beta 版本)
registry?: string; // NPM registry 地址,默认见 DEFAULT_NPM_REGISTRY
registry?: string; // NPM registry 地址,优先级:CLI > package.json publishConfig > npm config
}

export interface PublishManifest {
Expand Down
5 changes: 2 additions & 3 deletions packages/rush-plugins/publish/src/action/release/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { type Command } from 'commander';
import { logger } from '@coze-arch/logger';

import { type InstallAction } from '../../types';
import { DEFAULT_NPM_REGISTRY, DEFAULT_ALLOW_BRANCHES } from '../../const';
import { DEFAULT_ALLOW_BRANCHES } from '../../const';
import { type ReleaseOptions } from './types';
import { release } from './action';

Expand All @@ -17,8 +17,7 @@ export const installAction: InstallAction = (program: Command) => {
.option('--dry-run', '是否只执行不真实发布', false)
.option(
'-r, --registry <string>',
`发布到的 registry (默认: ${DEFAULT_NPM_REGISTRY})`,
DEFAULT_NPM_REGISTRY,
'发布到的 registry (优先级: CLI参数 > package.json publishConfig.registry > npm config)',
)
.option(
'--allow-branches <branches...>',
Expand Down
14 changes: 8 additions & 6 deletions packages/rush-plugins/publish/src/action/release/release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import { type RushConfigurationProject } from '@rushstack/rush-sdk';
import { logger } from '@coze-arch/logger';

import { resolveRegistry } from '../../utils/resolve-registry';
import { exec } from '../../utils/exec';
import { type ReleaseOptions, type ReleaseManifest } from './types';
import { type ReleaseManifest, type ReleaseOptions } from './types';
import { applyPublishConfig } from './package';

/**
Expand All @@ -15,23 +16,24 @@ const publishPackage = async (
project: RushConfigurationProject,
releaseOptions: ReleaseOptions,
): Promise<void> => {
const { dryRun, registry } = releaseOptions;
const { dryRun } = releaseOptions;
const token = process.env.NPM_AUTH_TOKEN;
const { version } = project.packageJson;
const tag = version.includes('alpha')
? 'alpha'
: version.includes('beta')
? 'beta'
: 'latest';
const setToken = `npm config set //bnpm.byted.org/:_authToken ${token}`;
await exec(setToken, {
cwd: project.projectFolder,
});

// 解析 registry:CLI 参数 > package.json publishConfig > npm 配置
const registry = resolveRegistry(project, releaseOptions.registry);

// 使用环境变量传递 authToken,npm 会自动应用到任何 registry
const args = [`NODE_AUTH_TOKEN=${token}`, 'npm', 'publish', `--tag ${tag}`];
if (dryRun) {
args.push('--dry-run');
}
// 只有明确指定了 registry 才传递参数,否则使用 npm 配置的默认值
if (registry) {
args.push(`--registry=${registry}`);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/rush-plugins/publish/src/action/release/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { type RushConfigurationProject } from '@rushstack/rush-sdk';
export interface ReleaseOptions {
commit?: string; // 可选,为空时使用当前 HEAD
dryRun?: boolean;
registry: string;
registry?: string; // 可选,优先级:CLI > package.json publishConfig > npm config
packages?: PackageToPublish[]; // 可选,直接传入需要发布的包列表
allowBranches?: string[]; // 可选,允许发布正式版本的分支列表
}
Expand Down
5 changes: 0 additions & 5 deletions packages/rush-plugins/publish/src/const/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
// Copyright (c) 2025 coze-dev
// SPDX-License-Identifier: MIT

/**
* 默认的 NPM registry 地址
*/
export const DEFAULT_NPM_REGISTRY = 'https://registry.npmjs.org';

/**
* 默认的 Git 分支名前缀
*/
Expand Down
Loading