mirror of
https://github.com/prompt-security/clawsec.git
synced 2026-06-19 08:21:21 +03:00
fix(skill-release): authenticate pinned clawhub install
This commit is contained in:
@@ -1685,6 +1685,10 @@ jobs:
|
||||
contents: read
|
||||
env:
|
||||
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }}
|
||||
AWS_REGION: eu-north-1
|
||||
steps:
|
||||
- name: Check if publishable
|
||||
if: needs.release-tag.outputs.publish_clawhub != 'true'
|
||||
@@ -1704,52 +1708,12 @@ jobs:
|
||||
|
||||
- name: Install clawhub CLI
|
||||
if: needs.release-tag.outputs.publish_clawhub == 'true' && env.CLAWHUB_TOKEN != ''
|
||||
run: |
|
||||
npm ci --prefix .github/clawhub-cli
|
||||
echo "${GITHUB_WORKSPACE}/.github/clawhub-cli/node_modules/.bin" >> "$GITHUB_PATH"
|
||||
run: bash scripts/ci/install_clawhub_cli.sh
|
||||
|
||||
- name: Patch clawhub publish payload workaround
|
||||
# Temporary: clawhub@0.7.0 publish payload is missing acceptLicenseTerms.
|
||||
if: needs.release-tag.outputs.publish_clawhub == 'true' && env.CLAWHUB_TOKEN != ''
|
||||
run: |
|
||||
node <<'NODE'
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
|
||||
const npmRoot = path.join(process.env.GITHUB_WORKSPACE, ".github", "clawhub-cli", "node_modules");
|
||||
const publishScriptPath = path.join(
|
||||
npmRoot,
|
||||
"clawhub",
|
||||
"dist",
|
||||
"cli",
|
||||
"commands",
|
||||
"publish.js"
|
||||
);
|
||||
|
||||
if (!fs.existsSync(publishScriptPath)) {
|
||||
throw new Error(`clawhub publish script not found: ${publishScriptPath}`);
|
||||
}
|
||||
|
||||
const original = fs.readFileSync(publishScriptPath, "utf8");
|
||||
if (original.includes("acceptLicenseTerms: true")) {
|
||||
console.log(`[patch-clawhub] Already patched: ${publishScriptPath}`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const payloadPattern = /changelog,\r?\n(\s*)tags,/;
|
||||
if (!payloadPattern.test(original)) {
|
||||
throw new Error(
|
||||
`[patch-clawhub] Could not find expected publish payload pattern in ${publishScriptPath}`
|
||||
);
|
||||
}
|
||||
|
||||
const patched = original.replace(
|
||||
payloadPattern,
|
||||
(_, indent) => `changelog,\n${indent}acceptLicenseTerms: true,\n${indent}tags,`
|
||||
);
|
||||
fs.writeFileSync(publishScriptPath, patched, "utf8");
|
||||
console.log(`[patch-clawhub] Patched: ${publishScriptPath}`);
|
||||
NODE
|
||||
run: node scripts/ci/patch_clawhub_publish_payload.mjs
|
||||
|
||||
- name: Login to ClawHub
|
||||
if: needs.release-tag.outputs.publish_clawhub == 'true' && env.CLAWHUB_TOKEN != ''
|
||||
@@ -1831,6 +1795,10 @@ jobs:
|
||||
contents: read
|
||||
env:
|
||||
CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }}
|
||||
AWS_REGION: eu-north-1
|
||||
steps:
|
||||
- name: Parse tag
|
||||
id: parse
|
||||
@@ -1895,51 +1863,11 @@ jobs:
|
||||
run: node scripts/ci/validate_skill_install_docs.mjs --skills "${{ steps.parse.outputs.skill_path }}"
|
||||
|
||||
- name: Install clawhub CLI
|
||||
run: |
|
||||
npm ci --prefix .github/clawhub-cli
|
||||
echo "${GITHUB_WORKSPACE}/.github/clawhub-cli/node_modules/.bin" >> "$GITHUB_PATH"
|
||||
run: bash scripts/ci/install_clawhub_cli.sh
|
||||
|
||||
- name: Patch clawhub publish payload workaround
|
||||
# Temporary: clawhub@0.7.0 publish payload is missing acceptLicenseTerms.
|
||||
run: |
|
||||
node <<'NODE'
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
|
||||
const npmRoot = path.join(process.env.GITHUB_WORKSPACE, ".github", "clawhub-cli", "node_modules");
|
||||
const publishScriptPath = path.join(
|
||||
npmRoot,
|
||||
"clawhub",
|
||||
"dist",
|
||||
"cli",
|
||||
"commands",
|
||||
"publish.js"
|
||||
);
|
||||
|
||||
if (!fs.existsSync(publishScriptPath)) {
|
||||
throw new Error(`clawhub publish script not found: ${publishScriptPath}`);
|
||||
}
|
||||
|
||||
const original = fs.readFileSync(publishScriptPath, "utf8");
|
||||
if (original.includes("acceptLicenseTerms: true")) {
|
||||
console.log(`[patch-clawhub] Already patched: ${publishScriptPath}`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const payloadPattern = /changelog,\r?\n(\s*)tags,/;
|
||||
if (!payloadPattern.test(original)) {
|
||||
throw new Error(
|
||||
`[patch-clawhub] Could not find expected publish payload pattern in ${publishScriptPath}`
|
||||
);
|
||||
}
|
||||
|
||||
const patched = original.replace(
|
||||
payloadPattern,
|
||||
(_, indent) => `changelog,\n${indent}acceptLicenseTerms: true,\n${indent}tags,`
|
||||
);
|
||||
fs.writeFileSync(publishScriptPath, patched, "utf8");
|
||||
console.log(`[patch-clawhub] Patched: ${publishScriptPath}`);
|
||||
NODE
|
||||
run: node scripts/ci/patch_clawhub_publish_payload.mjs
|
||||
|
||||
- name: Login to ClawHub
|
||||
run: |
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CLI_PREFIX="${CLAWHUB_CLI_PREFIX:-.github/clawhub-cli}"
|
||||
CODEARTIFACT_DOMAIN="${CODEARTIFACT_DOMAIN:-prompt-security}"
|
||||
CODEARTIFACT_DOMAIN_OWNER="${CODEARTIFACT_DOMAIN_OWNER:-443370709039}"
|
||||
CODEARTIFACT_REPOSITORY="${CODEARTIFACT_REPOSITORY:-npm-proxy}"
|
||||
AWS_REGION="${AWS_REGION:-${AWS_DEFAULT_REGION:-eu-north-1}}"
|
||||
|
||||
if ! command -v aws >/dev/null 2>&1; then
|
||||
echo "::error::aws CLI is required to authenticate npm against CodeArtifact"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! aws sts get-caller-identity >/dev/null 2>&1; then
|
||||
echo "::error::AWS credentials are required before installing the CodeArtifact-pinned clawhub CLI"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
aws codeartifact login \
|
||||
--tool npm \
|
||||
--domain "$CODEARTIFACT_DOMAIN" \
|
||||
--domain-owner "$CODEARTIFACT_DOMAIN_OWNER" \
|
||||
--repository "$CODEARTIFACT_REPOSITORY" \
|
||||
--region "$AWS_REGION"
|
||||
|
||||
npm ci --prefix "$CLI_PREFIX"
|
||||
|
||||
if [ -n "${GITHUB_PATH:-}" ]; then
|
||||
workspace="${GITHUB_WORKSPACE:-$(pwd)}"
|
||||
echo "${workspace}/${CLI_PREFIX}/node_modules/.bin" >> "$GITHUB_PATH"
|
||||
fi
|
||||
@@ -0,0 +1,35 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const workspace = process.env.GITHUB_WORKSPACE || process.cwd();
|
||||
const npmRoot = path.join(workspace, ".github", "clawhub-cli", "node_modules");
|
||||
const publishScriptPath = path.join(
|
||||
npmRoot,
|
||||
"clawhub",
|
||||
"dist",
|
||||
"cli",
|
||||
"commands",
|
||||
"publish.js",
|
||||
);
|
||||
|
||||
if (!fs.existsSync(publishScriptPath)) {
|
||||
throw new Error(`clawhub publish script not found: ${publishScriptPath}`);
|
||||
}
|
||||
|
||||
const original = fs.readFileSync(publishScriptPath, "utf8");
|
||||
if (original.includes("acceptLicenseTerms: true")) {
|
||||
console.log(`[patch-clawhub] Already patched: ${publishScriptPath}`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const payloadPattern = /changelog,\r?\n(\s*)tags,/;
|
||||
if (!payloadPattern.test(original)) {
|
||||
throw new Error(`[patch-clawhub] Could not find expected publish payload pattern in ${publishScriptPath}`);
|
||||
}
|
||||
|
||||
const patched = original.replace(
|
||||
payloadPattern,
|
||||
(_, indent) => `changelog,\n${indent}acceptLicenseTerms: true,\n${indent}tags,`,
|
||||
);
|
||||
fs.writeFileSync(publishScriptPath, patched, "utf8");
|
||||
console.log(`[patch-clawhub] Patched: ${publishScriptPath}`);
|
||||
@@ -3,8 +3,12 @@ import { readFile } from 'node:fs/promises';
|
||||
|
||||
const workflowPath = new URL('../.github/workflows/skill-release.yml', import.meta.url);
|
||||
const ciWorkflowPath = new URL('../.github/workflows/ci.yml', import.meta.url);
|
||||
const installClawhubCliPath = new URL('./ci/install_clawhub_cli.sh', import.meta.url);
|
||||
const patchClawhubPayloadPath = new URL('./ci/patch_clawhub_publish_payload.mjs', import.meta.url);
|
||||
const workflow = await readFile(workflowPath, 'utf8');
|
||||
const ciWorkflow = await readFile(ciWorkflowPath, 'utf8');
|
||||
const installClawhubCli = await readFile(installClawhubCliPath, 'utf8');
|
||||
const patchClawhubPayload = await readFile(patchClawhubPayloadPath, 'utf8');
|
||||
|
||||
assert.match(
|
||||
workflow,
|
||||
@@ -315,6 +319,68 @@ assert.match(
|
||||
'ClawHub publish must use the resolved ClawHub slug',
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
workflow.match(/bash scripts\/ci\/install_clawhub_cli\.sh/g)?.length,
|
||||
2,
|
||||
'ClawHub publish and republish jobs must share the same pinned CLI installer',
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
workflow.match(/node scripts\/ci\/patch_clawhub_publish_payload\.mjs/g)?.length,
|
||||
2,
|
||||
'ClawHub publish and republish jobs must share the same payload patch helper',
|
||||
);
|
||||
|
||||
assert.doesNotMatch(
|
||||
workflow,
|
||||
/npm ci --prefix \.github\/clawhub-cli/,
|
||||
'ClawHub CLI installation must not be duplicated inline in the workflow',
|
||||
);
|
||||
|
||||
assert.doesNotMatch(
|
||||
workflow,
|
||||
/node <<'NODE'[\s\S]*acceptLicenseTerms: true/,
|
||||
'ClawHub payload patching must not be duplicated inline in the workflow',
|
||||
);
|
||||
|
||||
for (const secret of ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_SESSION_TOKEN']) {
|
||||
assert.match(
|
||||
workflow,
|
||||
new RegExp(`${secret}: \\$\\{\\{ secrets\\.${secret} \\}\\}`),
|
||||
`ClawHub jobs must expose ${secret} for CodeArtifact npm authentication`,
|
||||
);
|
||||
}
|
||||
|
||||
assert.match(
|
||||
installClawhubCli,
|
||||
/aws codeartifact login[\s\S]*--domain "\$CODEARTIFACT_DOMAIN"[\s\S]*--domain-owner "\$CODEARTIFACT_DOMAIN_OWNER"[\s\S]*--repository "\$CODEARTIFACT_REPOSITORY"[\s\S]*--region "\$AWS_REGION"/,
|
||||
'ClawHub CLI installer must authenticate npm against CodeArtifact before npm ci',
|
||||
);
|
||||
|
||||
assert.match(
|
||||
installClawhubCli,
|
||||
/npm ci --prefix "\$CLI_PREFIX"/,
|
||||
'ClawHub CLI installer must install from the committed lockfile prefix',
|
||||
);
|
||||
|
||||
assert.match(
|
||||
installClawhubCli,
|
||||
/"\$\{workspace\}\/\$\{CLI_PREFIX\}\/node_modules\/\.bin" >> "\$GITHUB_PATH"/,
|
||||
'ClawHub CLI installer must expose the pinned clawhub binary on GITHUB_PATH',
|
||||
);
|
||||
|
||||
assert.match(
|
||||
patchClawhubPayload,
|
||||
/const payloadPattern = \/changelog,\\r\?\\n\(\\s\*\)tags,\/;/,
|
||||
'ClawHub payload patch helper must target the expected publish payload shape',
|
||||
);
|
||||
|
||||
assert.match(
|
||||
patchClawhubPayload,
|
||||
/acceptLicenseTerms: true/,
|
||||
'ClawHub payload patch helper must preserve the acceptLicenseTerms workaround',
|
||||
);
|
||||
|
||||
assert.doesNotMatch(
|
||||
workflow,
|
||||
/clawhub inspect "\$SKILL_NAME" --version "\$VERSION" --json/,
|
||||
|
||||
Reference in New Issue
Block a user