mirror of
https://github.com/openclaw/clawhub.git
synced 2026-08-14 00:47:57 +00:00
feat: forward package catalog metadata in publish workflow (#3074)
* feat: forward package catalog metadata in publish workflow * docs: make package publish metadata example event-safe * fix: preserve package metadata clearing --------- Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
This commit is contained in:
co-authored by
Patrick Erichsen
parent
31729d314c
commit
6d935f0595
@@ -59,6 +59,28 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
default: latest
|
||||
changelog:
|
||||
description: Optional release changelog shown on ClawHub.
|
||||
required: false
|
||||
type: string
|
||||
categories:
|
||||
description: Optional comma-separated plugin category slugs.
|
||||
required: false
|
||||
type: string
|
||||
clear_categories:
|
||||
description: Clear existing plugin categories. Cannot be combined with categories.
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
topics:
|
||||
description: Optional comma-separated catalog topics.
|
||||
required: false
|
||||
type: string
|
||||
clear_topics:
|
||||
description: Clear existing catalog topics. Cannot be combined with topics.
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
source_repo:
|
||||
description: Optional source repo override for local-folder publishes.
|
||||
required: false
|
||||
@@ -312,6 +334,11 @@ jobs:
|
||||
INPUT_FAMILY: ${{ inputs.family }}
|
||||
INPUT_VERSION: ${{ inputs.version }}
|
||||
INPUT_TAGS: ${{ inputs.tags }}
|
||||
INPUT_CHANGELOG: ${{ inputs.changelog }}
|
||||
INPUT_CATEGORIES: ${{ inputs.categories }}
|
||||
INPUT_CLEAR_CATEGORIES: ${{ inputs.clear_categories }}
|
||||
INPUT_TOPICS: ${{ inputs.topics }}
|
||||
INPUT_CLEAR_TOPICS: ${{ inputs.clear_topics }}
|
||||
INPUT_SOURCE_REPO: ${{ inputs.source_repo }}
|
||||
INPUT_SOURCE_COMMIT: ${{ inputs.source_commit }}
|
||||
INPUT_SOURCE_REF: ${{ inputs.source_ref }}
|
||||
@@ -478,6 +505,15 @@ jobs:
|
||||
family = os.environ["INPUT_FAMILY"].strip()
|
||||
version = os.environ["INPUT_VERSION"].strip()
|
||||
tags = os.environ["INPUT_TAGS"].strip()
|
||||
changelog = os.environ["INPUT_CHANGELOG"].strip()
|
||||
categories = os.environ["INPUT_CATEGORIES"].strip()
|
||||
clear_categories = os.environ["INPUT_CLEAR_CATEGORIES"].strip().lower() == "true"
|
||||
topics = os.environ["INPUT_TOPICS"].strip()
|
||||
clear_topics = os.environ["INPUT_CLEAR_TOPICS"].strip().lower() == "true"
|
||||
if categories and clear_categories:
|
||||
raise SystemExit("categories and clear_categories cannot be combined")
|
||||
if topics and clear_topics:
|
||||
raise SystemExit("topics and clear_topics cannot be combined")
|
||||
if owner:
|
||||
cmd += ["--owner", owner]
|
||||
if family:
|
||||
@@ -491,6 +527,16 @@ jobs:
|
||||
cmd += ["--version", version]
|
||||
if tags:
|
||||
cmd += ["--tags", tags]
|
||||
if changelog:
|
||||
cmd += ["--changelog", changelog]
|
||||
if categories:
|
||||
cmd += ["--categories", categories]
|
||||
elif clear_categories:
|
||||
cmd += ["--categories", ""]
|
||||
if topics:
|
||||
cmd += ["--topics", topics]
|
||||
elif clear_topics:
|
||||
cmd += ["--topics", ""]
|
||||
source_repo = os.environ["INPUT_SOURCE_REPO"].strip()
|
||||
source_commit = os.environ["INPUT_SOURCE_COMMIT"].strip()
|
||||
source_ref = os.environ["INPUT_SOURCE_REF"].strip()
|
||||
|
||||
+18
@@ -797,11 +797,29 @@ jobs:
|
||||
clawhub_token: ${{ secrets.CLAWHUB_TOKEN }}
|
||||
```
|
||||
|
||||
To attach release and catalog metadata, add the matching CLI values to the
|
||||
job's existing `with` block. Keep `dry_run: true` on pull-request jobs; use
|
||||
`dry_run: false` only on the trusted publish job shown above.
|
||||
|
||||
```yaml
|
||||
with:
|
||||
changelog: "Describe the changes in this release."
|
||||
categories: "tools"
|
||||
topics: "automation,productivity"
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- The reusable workflow defaults `source` to the caller repo.
|
||||
- For monorepos, pass `source_path` so the workflow publishes the plugin
|
||||
package folder, for example `source_path: extensions/codex`.
|
||||
- `changelog`, `categories`, and `topics` are optional. When present, the
|
||||
workflow forwards them to the matching package publish CLI flags. Categories
|
||||
and topics use comma-separated values; omitting them preserves the existing
|
||||
workflow behavior.
|
||||
- To remove previously declared metadata, set `clear_categories: true` or
|
||||
`clear_topics: true`. A clear input cannot be combined with its matching
|
||||
value input.
|
||||
- Pin the reusable workflow to a stable tag or full commit SHA. Do not run release publishing from `@main`.
|
||||
- `pull_request` should use `dry_run: true` so CI stays non-polluting.
|
||||
- Real publishes should be limited to trusted events such as `workflow_dispatch` or tag pushes.
|
||||
|
||||
@@ -186,4 +186,50 @@ describe("package publish workflow", () => {
|
||||
expect(workflow).not.toContain("Prebuilt artifact mode does not accept source_path");
|
||||
expect(workflow).toContain('cmd += ["--source-path", source_path]');
|
||||
});
|
||||
|
||||
it("forwards optional catalog metadata and changelog inputs", () => {
|
||||
const workflowText = readFileSync(resolve(".github/workflows/package-publish.yml"), "utf8");
|
||||
const workflow = parseYaml(workflowText) as {
|
||||
on?: {
|
||||
workflow_call?: {
|
||||
inputs?: Record<string, { required?: boolean; type?: string }>;
|
||||
};
|
||||
};
|
||||
jobs?: {
|
||||
publish?: {
|
||||
steps?: Array<{ name?: string; env?: Record<string, string>; run?: string }>;
|
||||
};
|
||||
};
|
||||
};
|
||||
const inputs = workflow.on?.workflow_call?.inputs;
|
||||
const resolveStep = workflow.jobs?.publish?.steps?.find(
|
||||
(step) => step.name === "Resolve publish command",
|
||||
);
|
||||
|
||||
for (const name of ["changelog", "categories", "topics"]) {
|
||||
const envName = `INPUT_${name.toUpperCase()}`;
|
||||
expect(inputs?.[name]).toMatchObject({ required: false, type: "string" });
|
||||
expect(resolveStep?.env?.[envName]).toBe(`\${{ inputs.${name} }}`);
|
||||
expect(resolveStep?.run).toContain(`${name} = os.environ["${envName}"].strip()`);
|
||||
expect(resolveStep?.run).toContain(`if ${name}:\n cmd += ["--${name}", ${name}]`);
|
||||
}
|
||||
|
||||
for (const name of ["categories", "topics"]) {
|
||||
const clearName = `clear_${name}`;
|
||||
const envName = `INPUT_CLEAR_${name.toUpperCase()}`;
|
||||
expect(inputs?.[clearName]).toMatchObject({
|
||||
required: false,
|
||||
type: "boolean",
|
||||
default: false,
|
||||
});
|
||||
expect(resolveStep?.env?.[envName]).toBe(`\${{ inputs.${clearName} }}`);
|
||||
expect(resolveStep?.run).toContain(
|
||||
`${clearName} = os.environ["${envName}"].strip().lower() == "true"`,
|
||||
);
|
||||
expect(resolveStep?.run).toContain(
|
||||
`if ${name} and ${clearName}:\n raise SystemExit("${name} and ${clearName} cannot be combined")`,
|
||||
);
|
||||
expect(resolveStep?.run).toContain(`elif ${clearName}:\n cmd += ["--${name}", ""]`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user