Merge remote-tracking branch 'origin/main' into feat/commit-attribution

# Conflicts:
#	packages/core/src/core/client.ts
This commit is contained in:
wenshao 2026-05-06 15:02:52 +08:00
commit acd06e3461
81 changed files with 10065 additions and 1420 deletions

View file

@ -20,7 +20,9 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const PACKAGE_NAME = 'qwen-code-sdk';
const TAG_PREFIX = 'sdk-python-';
const TAG_PREFIX = 'sdk-python-v';
const NETWORK_COMMAND_TIMEOUT_MS = 30_000;
const LOCAL_COMMAND_TIMEOUT_MS = 10_000;
function readPyprojectVersion() {
const pyprojectPath = join(__dirname, '..', 'pyproject.toml');
@ -117,7 +119,7 @@ function toBaseVersion(version) {
async function getAllVersionsFromPyPI() {
const response = await fetch(`https://pypi.org/pypi/${PACKAGE_NAME}/json`, {
headers: { Accept: 'application/json' },
signal: AbortSignal.timeout(30_000),
signal: AbortSignal.timeout(NETWORK_COMMAND_TIMEOUT_MS),
});
if (response.status === 404) {
@ -241,28 +243,67 @@ function getUtcTimestamp() {
}
function getGitShortHash() {
return execSync('git rev-parse --short HEAD').toString().trim();
try {
return execSync('git rev-parse --short HEAD', {
timeout: LOCAL_COMMAND_TIMEOUT_MS,
})
.toString()
.trim();
} catch (error) {
if (isTimeoutError(error)) {
throw new Error(
`git rev-parse timed out after ${LOCAL_COMMAND_TIMEOUT_MS / 1000}s — local git may be unresponsive`,
);
}
throw error;
}
}
async function getReleaseState({ packageVersion, releaseTag }, allVersions) {
function isTimeoutError(error) {
// Node.js execSync timeout: `code` is 'ETIMEDOUT' on POSIX; on some
// versions/platforms `killed` is true with signal 'SIGTERM' or null.
// Match the pattern used in packages/core/src/utils/pdf.ts.
return (
error.code === 'ETIMEDOUT' ||
(error.killed === true &&
(error.signal === 'SIGTERM' ||
error.signal === undefined ||
error.signal === null))
);
}
async function getReleaseState(
{ packageVersion, releaseVersion },
allVersions,
) {
const state = {
packageVersionExistsOnPyPI: allVersions.includes(packageVersion),
gitTagExists: false,
githubReleaseExists: false,
};
const fullTag = `${TAG_PREFIX}${releaseTag}`;
const fullTag = `${TAG_PREFIX}${releaseVersion}`;
try {
const tagOutput = execSync(`git tag -l '${fullTag}'`).toString().trim();
const tagOutput = execSync(`git tag -l '${fullTag}'`, {
timeout: LOCAL_COMMAND_TIMEOUT_MS,
})
.toString()
.trim();
if (tagOutput === fullTag) {
state.gitTagExists = true;
}
} catch (error) {
if (isTimeoutError(error)) {
throw new Error(
`git tag -l timed out after ${LOCAL_COMMAND_TIMEOUT_MS / 1000}s — local git may be unresponsive`,
);
}
throw new Error(`Failed to check git tags for conflicts: ${error.message}`);
}
try {
const output = execSync(
`gh release view "${fullTag}" --json tagName --jq .tagName`,
{ timeout: NETWORK_COMMAND_TIMEOUT_MS },
)
.toString()
.trim();
@ -270,6 +311,13 @@ async function getReleaseState({ packageVersion, releaseTag }, allVersions) {
state.githubReleaseExists = true;
}
} catch (error) {
// Timeout check must precede isExpectedMissingGitHubRelease — a timed-out
// process may emit partial stderr matching "release not found".
if (isTimeoutError(error)) {
throw new Error(
`gh release view timed out after ${NETWORK_COMMAND_TIMEOUT_MS / 1000}s checking "${fullTag}" — GitHub API may be unavailable`,
);
}
if (!isExpectedMissingGitHubRelease(error)) {
throw new Error(
`Failed to check GitHub releases for conflicts: ${error.message}`,
@ -435,7 +483,7 @@ async function getVersion(options = {}) {
const releaseState = await getReleaseState(
{
packageVersion: versionData.packageVersion,
releaseTag: `v${versionData.releaseVersion}`,
releaseVersion: versionData.releaseVersion,
},
allVersions,
);
@ -481,11 +529,11 @@ async function getVersion(options = {}) {
if (releaseState.githubReleaseExists) {
console.error(
`GitHub release ${TAG_PREFIX}v${versionData.releaseVersion} already exists.`,
`GitHub release ${TAG_PREFIX}${versionData.releaseVersion} already exists.`,
);
} else if (releaseState.gitTagExists) {
console.error(
`::warning::Orphan git tag ${TAG_PREFIX}v${versionData.releaseVersion} exists without a PyPI version or GitHub release. Skipping to next version slot.`,
`::warning::Orphan git tag ${TAG_PREFIX}${versionData.releaseVersion} exists without a PyPI version or GitHub release. Skipping to next version slot.`,
);
} else if (releaseState.packageVersionExistsOnPyPI) {
console.error(