fix(release): align npm authority selection

This commit is contained in:
Vincent Koc
2026-08-21 02:29:15 -07:00
parent 7c8153d4b8
commit 0ff85cda2e
7 changed files with 68 additions and 27 deletions
+3 -2
View File
@@ -7,11 +7,12 @@ on:
- main
paths:
- ".github/workflows/plugin-npm-release.yml"
- ".github/actions/setup-node-env/**"
- "extensions/**"
- "package.json"
- "pnpm-lock.yaml"
- "packages/normalization-core/**"
- "packages/plugin-package-contract/src/index.ts"
- "packages/normalization-core/src/**"
- "packages/plugin-package-contract/src/**"
- "scripts/generate-npm-package-lock.mjs"
- "scripts/generate-npm-package-lock.mts"
- "scripts/lib/npm-publish-plan.mjs"
+7 -7
View File
@@ -6,8 +6,8 @@ import { join, resolve } from "node:path";
import { expectDefined } from "../../packages/normalization-core/src/expect.js";
import {
collectExtensionPackageJsonCandidates,
hasPluginPublicationSharedAuthorityChanges,
PLUGIN_PUBLICATION_SHARED_AUTHORITY_PATHS,
hasPluginNpmReleaseAuthorityChanges,
PLUGIN_NPM_RELEASE_AUTHORITY_PATHS,
} from "./plugin-publication-candidates.ts";
import {
assertUniquePublishablePluginPackageSources,
@@ -49,8 +49,8 @@ export type GitRangeSelection = {
};
export type PluginNpmGitRangeSelection = {
authorityChanged: boolean;
changedExtensionIds: string[];
sharedAuthorityChanged: boolean;
};
type ParsedPluginReleaseArgs = {
@@ -338,11 +338,11 @@ export function collectPluginNpmGitRangeSelection(params: {
const changedPaths = collectChangedPathsFromGitRange({
rootDir: params.rootDir,
gitRange: params.gitRange,
pathspecs: ["extensions", ...PLUGIN_PUBLICATION_SHARED_AUTHORITY_PATHS],
pathspecs: ["extensions", ...PLUGIN_NPM_RELEASE_AUTHORITY_PATHS],
});
return {
authorityChanged: hasPluginNpmReleaseAuthorityChanges(changedPaths),
changedExtensionIds: collectChangedExtensionIdsFromPaths(changedPaths),
sharedAuthorityChanged: hasPluginPublicationSharedAuthorityChanges(changedPaths),
};
}
@@ -506,7 +506,7 @@ export function collectPluginReleasePlan(params?: {
extensionIds:
params?.selectionMode === "all-publishable" ||
!gitRangeSelection ||
gitRangeSelection.sharedAuthorityChanged
gitRangeSelection.authorityChanged
? undefined
: gitRangeSelection.changedExtensionIds,
packageNames: params?.selection && params.selection.length > 0 ? params.selection : undefined,
@@ -521,7 +521,7 @@ export function collectPluginReleasePlan(params?: {
selection: params.selection,
})
: gitRangeSelection
? gitRangeSelection.sharedAuthorityChanged
? gitRangeSelection.authorityChanged
? allPublishable
: resolveChangedPublishablePluginPackages({
plugins: allPublishable,
+36 -4
View File
@@ -10,22 +10,54 @@ import type {
export const PLUGIN_PUBLICATION_SHARED_AUTHORITY_PATHS = [
"package.json",
"pnpm-lock.yaml",
"packages/normalization-core/src/string-coerce.ts",
"packages/plugin-package-contract/src/index.ts",
"packages/normalization-core/src",
"packages/plugin-package-contract/src",
"scripts/lib/npm-publish-plan.mjs",
"scripts/lib/plugin-publication-candidates.ts",
"scripts/lib/plugin-publication-collector.ts",
"scripts/lib/release-version.mjs",
] as const;
export function hasPluginPublicationSharedAuthorityChanges(paths: readonly string[]): boolean {
export const PLUGIN_NPM_RELEASE_AUTHORITY_PATHS = [
...PLUGIN_PUBLICATION_SHARED_AUTHORITY_PATHS,
".github/actions/setup-node-env",
".github/workflows/plugin-npm-release.yml",
"scripts/generate-npm-package-lock.mjs",
"scripts/generate-npm-package-lock.mts",
"scripts/lib/actions-artifact-archive.mjs",
"scripts/lib/npm-json-output.mts",
"scripts/lib/plugin-npm-package-manifest.mjs",
"scripts/lib/plugin-npm-package-manifest.mts",
"scripts/lib/plugin-npm-release.ts",
"scripts/lib/tsx-cli-shim.mjs",
"scripts/plugin-npm-publish.sh",
"scripts/plugin-npm-release-check.ts",
"scripts/plugin-npm-release-plan.ts",
"scripts/plugin-publication-artifact.mjs",
"scripts/release-tooling-identity.d.mts",
"scripts/release-tooling-identity.mjs",
"scripts/verify-plugin-npm-published-runtime.mts",
] as const;
function hasAuthorityPathChanges(
paths: readonly string[],
authorityPaths: readonly string[],
): boolean {
return paths.some((path) =>
PLUGIN_PUBLICATION_SHARED_AUTHORITY_PATHS.some(
authorityPaths.some(
(authorityPath) => path === authorityPath || path.startsWith(`${authorityPath}/`),
),
);
}
export function hasPluginPublicationSharedAuthorityChanges(paths: readonly string[]): boolean {
return hasAuthorityPathChanges(paths, PLUGIN_PUBLICATION_SHARED_AUTHORITY_PATHS);
}
export function hasPluginNpmReleaseAuthorityChanges(paths: readonly string[]): boolean {
return hasAuthorityPathChanges(paths, PLUGIN_NPM_RELEASE_AUTHORITY_PATHS);
}
function readPluginPackageJson(absolutePath: string, repoPath: string): PluginPackageJson {
let raw: string;
try {
+2 -2
View File
@@ -25,7 +25,7 @@ function runPluginNpmReleaseCheck(argv: string[]) {
extensionIds:
selectionMode === "all-publishable" ||
!gitRangeSelection ||
gitRangeSelection.sharedAuthorityChanged
gitRangeSelection.authorityChanged
? undefined
: gitRangeSelection.changedExtensionIds,
packageNames: selection.length > 0 ? selection : undefined,
@@ -40,7 +40,7 @@ function runPluginNpmReleaseCheck(argv: string[]) {
selection,
})
: gitRangeSelection
? gitRangeSelection.sharedAuthorityChanged
? gitRangeSelection.authorityChanged
? publishable
: resolveChangedPublishablePluginPackages({
plugins: publishable,
+2 -1
View File
@@ -424,7 +424,8 @@ describe("resolveSelectedClawHubPublishablePluginPackages", () => {
});
it.each([
"packages/normalization-core/src/string-coerce.ts",
"packages/normalization-core/src/record-coerce.ts",
"packages/plugin-package-contract/src/schema.ts",
"scripts/lib/plugin-publication-candidates.ts",
"scripts/lib/plugin-publication-collector.ts",
])("selects all publishable plugins when %s changes", (changedPath) => {
+6 -3
View File
@@ -824,10 +824,13 @@ describe("collectChangedExtensionIdsFromPaths", () => {
describe("collectPluginNpmGitRangeSelection", () => {
it.each([
"packages/normalization-core/src/string-coerce.ts",
".github/actions/setup-node-env/action.yml",
"packages/normalization-core/src/record-coerce.ts",
"packages/plugin-package-contract/src/schema.ts",
"scripts/lib/plugin-publication-candidates.ts",
"scripts/lib/plugin-publication-collector.ts",
])("selects all publishable plugins for a shared-only %s change", (changedPath) => {
"scripts/plugin-npm-release-plan.ts",
])("selects all publishable plugins for an authority-only %s change", (changedPath) => {
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-range-");
const absolutePath = join(repoDir, changedPath);
mkdirSync(dirname(absolutePath), { recursive: true });
@@ -878,8 +881,8 @@ describe("collectPluginNpmGitRangeSelection", () => {
gitRange: { baseRef, headRef },
}),
).toEqual({
authorityChanged: true,
changedExtensionIds: [],
sharedAuthorityChanged: true,
});
});
});
@@ -1,7 +1,7 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
import { parse } from "yaml";
import { PLUGIN_PUBLICATION_SHARED_AUTHORITY_PATHS } from "../../scripts/lib/plugin-publication-candidates.ts";
import { PLUGIN_NPM_RELEASE_AUTHORITY_PATHS } from "../../scripts/lib/plugin-publication-candidates.ts";
const workflowPath = ".github/workflows/plugin-npm-release.yml";
const metaPackagePath = "extensions/meta/package.json";
@@ -64,14 +64,18 @@ function workflowPathPatternCovers(pattern: string, path: string): boolean {
}
describe("plugin npm extended-stable workflow", () => {
it("triggers for every shared plugin publication authority", () => {
const triggerPaths = workflow().on?.push?.paths ?? [];
for (const authorityPath of PLUGIN_PUBLICATION_SHARED_AUTHORITY_PATHS) {
expect(
it("keeps push triggers aligned with npm publication authorities", () => {
const triggerPaths = (workflow().on?.push?.paths ?? []).filter(
(path) => path !== "extensions/**",
);
expect(
triggerPaths.map((path) => (path.endsWith("/**") ? path.slice(0, -3) : path)).toSorted(),
).toEqual([...PLUGIN_NPM_RELEASE_AUTHORITY_PATHS].toSorted());
expect(
PLUGIN_NPM_RELEASE_AUTHORITY_PATHS.every((authorityPath) =>
triggerPaths.some((pattern) => workflowPathPatternCovers(pattern, authorityPath)),
authorityPath,
).toBe(true);
}
),
).toBe(true);
});
it("exposes only the default behavior and closed extended-stable override", () => {