mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(release): keep msteams packaging and Docker reruns reliable (#113332)
* fix(release): forward-port beta packaging repairs * fix(ci): acknowledge sweeper token grant
This commit is contained in:
committed by
GitHub
parent
8d67c40939
commit
7dfb660d1f
@@ -39,13 +39,13 @@ jobs:
|
||||
# lack actions:write/checks:read (every sweep failed 2026-07-24 until the
|
||||
# subset was reverted). No inputs = the app's full granted set, which the
|
||||
# sweep's re-fire lane is known to work with.
|
||||
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
|
||||
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # zizmor: ignore[github-app] v3
|
||||
id: app-token
|
||||
continue-on-error: true
|
||||
with:
|
||||
app-id: "2729701"
|
||||
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3
|
||||
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # zizmor: ignore[github-app] v3
|
||||
id: app-token-fallback
|
||||
if: steps.app-token.outcome == 'failure'
|
||||
with:
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
"runtimeFormat": "cjs"
|
||||
},
|
||||
"release": {
|
||||
"bundleRuntimeDependencies": false,
|
||||
"publishToClawHub": true,
|
||||
"publishToNpm": true
|
||||
}
|
||||
|
||||
@@ -417,10 +417,14 @@ function downloadDockerArtifacts(runId, repo, outputDir) {
|
||||
if (names.length === 0) {
|
||||
throw new Error(`No docker-e2e-* artifacts found for run ${runId}`);
|
||||
}
|
||||
for (const name of names) {
|
||||
for (const [index, name] of names.entries()) {
|
||||
const artifactDir = path.join(
|
||||
outputDir,
|
||||
`${String(index).padStart(3, "0")}-${safePathSegment(name)}`,
|
||||
);
|
||||
run(
|
||||
"gh",
|
||||
["run", "download", String(runId), "--repo", repo, "--name", name, "--dir", outputDir],
|
||||
["run", "download", String(runId), "--repo", repo, "--name", name, "--dir", artifactDir],
|
||||
{
|
||||
stdio: "inherit",
|
||||
},
|
||||
|
||||
@@ -140,6 +140,14 @@ function writeOptionalPlatformDependencyPackage(packageDir: string): string {
|
||||
}
|
||||
|
||||
describe("plugin npm package manifest staging", () => {
|
||||
it("keeps msteams runtime dependencies registry-installed", () => {
|
||||
const packageJson = JSON.parse(
|
||||
readFileSync(join(process.cwd(), "extensions", "msteams", "package.json"), "utf8"),
|
||||
) as { openclaw?: { release?: { bundleRuntimeDependencies?: boolean } } };
|
||||
|
||||
expect(packageJson.openclaw?.release?.bundleRuntimeDependencies).toBe(false);
|
||||
});
|
||||
|
||||
it("wraps Windows npm.cmd staging through cmd.exe without shell mode", () => {
|
||||
const nodeDir = "C:\\Program Files\\nodejs";
|
||||
const npmCmdPath = win32.resolve(nodeDir, "npm.cmd");
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
readFileSync,
|
||||
readdirSync,
|
||||
rmSync,
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
@@ -687,8 +688,22 @@ describe("Docker E2E helper CLIs", () => {
|
||||
expect(firstDir).not.toBe(secondDir);
|
||||
expect(path.basename(firstDir)).toMatch(/^openclaw-docker-e2e-rerun-12345-/u);
|
||||
expect(path.basename(secondDir)).toMatch(/^openclaw-docker-e2e-rerun-12345-/u);
|
||||
expect(existsSync(path.join(firstDir, "artifact", "failures.json"))).toBe(true);
|
||||
expect(existsSync(path.join(secondDir, "artifact", "failures.json"))).toBe(true);
|
||||
const firstArtifactDir = readdirSync(firstDir, { withFileTypes: true }).find((entry) =>
|
||||
entry.isDirectory(),
|
||||
);
|
||||
const secondArtifactDir = readdirSync(secondDir, { withFileTypes: true }).find((entry) =>
|
||||
entry.isDirectory(),
|
||||
);
|
||||
expect(firstArtifactDir).toBeDefined();
|
||||
expect(secondArtifactDir).toBeDefined();
|
||||
expect(
|
||||
existsSync(path.join(firstDir, firstArtifactDir?.name ?? "", "artifact", "failures.json")),
|
||||
).toBe(true);
|
||||
expect(
|
||||
existsSync(
|
||||
path.join(secondDir, secondArtifactDir?.name ?? "", "artifact", "failures.json"),
|
||||
),
|
||||
).toBe(true);
|
||||
expect(first.stdout).toContain(`-f ref='${"d".repeat(40)}'`);
|
||||
expect(first.stdout).not.toContain("-f ref='abc123'");
|
||||
expect(second.stdout).toContain(`-f ref='${"d".repeat(40)}'`);
|
||||
@@ -700,6 +715,81 @@ describe("Docker E2E helper CLIs", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("isolates files with the same name across downloaded artifacts", () => {
|
||||
const root = mkdtempSync(`${tmpdir()}/openclaw-docker-e2e-rerun-collisions-`);
|
||||
try {
|
||||
const binDir = path.join(root, "bin");
|
||||
const outputDir = path.join(root, "artifacts");
|
||||
const ghPath = path.join(binDir, "gh");
|
||||
mkdirSync(binDir, { recursive: true });
|
||||
writeFileSync(
|
||||
ghPath,
|
||||
[
|
||||
"#!/usr/bin/env node",
|
||||
"const fs = require('node:fs');",
|
||||
"const path = require('node:path');",
|
||||
"const args = process.argv.slice(2);",
|
||||
"if (args[0] === 'run' && args[1] === 'view') {",
|
||||
" console.log(JSON.stringify({ headBranch: 'main', headSha: 'f'.repeat(40), url: 'https://example.invalid/run', workflowName: 'Live E2E' }));",
|
||||
" process.exit(0);",
|
||||
"}",
|
||||
"if (args[0] === 'api') {",
|
||||
" console.log(JSON.stringify([",
|
||||
" { expired: false, name: 'docker-e2e-a' },",
|
||||
" { expired: false, name: 'docker-e2e-b' },",
|
||||
" ]));",
|
||||
" process.exit(0);",
|
||||
"}",
|
||||
"if (args[0] === 'run' && args[1] === 'download') {",
|
||||
" const name = args[args.indexOf('--name') + 1];",
|
||||
" const dir = args[args.indexOf('--dir') + 1];",
|
||||
" fs.mkdirSync(dir, { recursive: true });",
|
||||
" const plan = path.join(dir, 'targeted-plan.json');",
|
||||
" if (fs.existsSync(plan)) {",
|
||||
" console.error('targeted-plan.json already exists');",
|
||||
" process.exit(2);",
|
||||
" }",
|
||||
" fs.writeFileSync(plan, '{}');",
|
||||
" fs.writeFileSync(path.join(dir, 'failures.json'), JSON.stringify({",
|
||||
" lanes: [{ name: name.endsWith('-a') ? 'gateway-network' : 'install-e2e', status: 1 }],",
|
||||
" ref: 'd'.repeat(40),",
|
||||
" status: 'failed',",
|
||||
" }));",
|
||||
" process.exit(0);",
|
||||
"}",
|
||||
"console.error(`unexpected gh args: ${args.join(' ')}`);",
|
||||
"process.exit(1);",
|
||||
"",
|
||||
].join("\n"),
|
||||
"utf8",
|
||||
);
|
||||
chmodSync(ghPath, 0o755);
|
||||
|
||||
const result = runHelper(
|
||||
"scripts/docker-e2e-rerun.mjs",
|
||||
"12345",
|
||||
"--repo",
|
||||
"openclaw/openclaw",
|
||||
"--dir",
|
||||
outputDir,
|
||||
{ PATH: `${binDir}${path.delimiter}${process.env.PATH ?? ""}` },
|
||||
);
|
||||
|
||||
expect(result.status, result.stderr).toBe(0);
|
||||
expect(result.stdout).toContain("gateway-network");
|
||||
expect(result.stdout).toContain("install-e2e");
|
||||
const artifactDirs = readdirSync(outputDir, { withFileTypes: true }).filter((entry) =>
|
||||
entry.isDirectory(),
|
||||
);
|
||||
expect(artifactDirs).toHaveLength(2);
|
||||
for (const entry of artifactDirs) {
|
||||
expect(existsSync(path.join(outputDir, entry.name, "targeted-plan.json"))).toBe(true);
|
||||
}
|
||||
} finally {
|
||||
rmSync(root, { force: true, recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("fails closed when downloaded artifacts contain mixed target refs", () => {
|
||||
const root = mkdtempSync(`${tmpdir()}/openclaw-docker-e2e-rerun-mixed-refs-`);
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user