diff --git a/.github/clawhub-cli/package-lock.json b/.github/clawhub-cli/package-lock.json new file mode 100644 index 0000000..7f4615b --- /dev/null +++ b/.github/clawhub-cli/package-lock.json @@ -0,0 +1,406 @@ +{ + "name": "clawhub-cli-pin", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "clawhub-cli-pin", + "dependencies": { + "clawhub": "0.7.0" + } + }, + "node_modules/@ark/schema": { + "version": "0.56.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/@ark/schema/-/schema-0.56.0.tgz", + "integrity": "sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA==", + "dependencies": { + "@ark/util": "0.56.0" + } + }, + "node_modules/@ark/util": { + "version": "0.56.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/@ark/util/-/util-0.56.0.tgz", + "integrity": "sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA==" + }, + "node_modules/@clack/core": { + "version": "0.5.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/@clack/core/-/core-0.5.0.tgz", + "integrity": "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==", + "dependencies": { + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/@clack/prompts": { + "version": "0.11.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/@clack/prompts/-/prompts-0.11.0.tgz", + "integrity": "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==", + "dependencies": { + "@clack/core": "0.5.0", + "picocolors": "^1.0.0", + "sisteransi": "^1.0.5" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/arkregex": { + "version": "0.0.5", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/arkregex/-/arkregex-0.0.5.tgz", + "integrity": "sha512-ncYjBdLlh5/QnVsAA8De16Tc9EqmYM7y/WU9j+236KcyYNUXogpz3sC4ATIZYzzLxwI+0sEOaQLEmLmRleaEXw==", + "dependencies": { + "@ark/util": "0.56.0" + } + }, + "node_modules/arktype": { + "version": "2.2.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/arktype/-/arktype-2.2.0.tgz", + "integrity": "sha512-t54MZ7ti5BhOEvzEkgKnWvqj+UbDfWig+DHr5I34xatymPusKLS0lQpNJd8M6DzmIto2QGszHfNKoFIT8tMCZQ==", + "dependencies": { + "@ark/schema": "0.56.0", + "@ark/util": "0.56.0", + "arkregex": "0.0.5" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/clawhub": { + "version": "0.7.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/clawhub/-/clawhub-0.7.0.tgz", + "integrity": "sha512-volW6SbX8PawlnRxxCoUTKv5Pi+N3MrBi3hlO5/m9bVaO43UFciEeYti9+01c2U5n/SKhUkw7ASvnleyNmcoSA==", + "dependencies": { + "@clack/prompts": "^0.11.0", + "arktype": "^2.1.29", + "commander": "^14.0.2", + "fflate": "^0.8.2", + "ignore": "^7.0.5", + "json5": "^2.2.3", + "mime": "^4.1.0", + "ora": "^9.0.0", + "p-retry": "^7.1.1", + "semver": "^7.7.3", + "undici": "^7.16.0" + }, + "bin": { + "clawdhub": "bin/clawdhub.js", + "clawhub": "bin/clawdhub.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "3.4.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/cli-spinners/-/cli-spinners-3.4.0.tgz", + "integrity": "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==", + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "engines": { + "node": ">=20" + } + }, + "node_modules/fflate": { + "version": "0.8.3", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==" + }, + "node_modules/get-east-asian-width": { + "version": "1.6.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", + "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-network-error": { + "version": "1.3.2", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/is-network-error/-/is-network-error-1.3.2.tgz", + "integrity": "sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/log-symbols": { + "version": "7.0.1", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/log-symbols/-/log-symbols-7.0.1.tgz", + "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", + "dependencies": { + "is-unicode-supported": "^2.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime": { + "version": "4.1.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/mime/-/mime-4.1.0.tgz", + "integrity": "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw==", + "funding": [ + "https://github.com/sponsors/broofa" + ], + "bin": { + "mime": "bin/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "9.4.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/ora/-/ora-9.4.0.tgz", + "integrity": "sha512-84cglkRILFxdtA8hAvLNdMrtBpPNBTrQ9/ulg0FA7xLMnD6mifv+enAIeRmvtv+WgdCE+LPGOfQmtJRrVaIVhQ==", + "dependencies": { + "chalk": "^5.6.2", + "cli-cursor": "^5.0.0", + "cli-spinners": "^3.2.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.1.0", + "log-symbols": "^7.0.1", + "stdin-discarder": "^0.3.2", + "string-width": "^8.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "7.1.1", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/p-retry/-/p-retry-7.1.1.tgz", + "integrity": "sha512-J5ApzjyRkkf601HpEeykoiCvzHQjWxPAHhyjFcEUP2SWq0+35NKh8TLhpLw+Dkq5TZBFvUM6UigdE9hIVYTl5w==", + "dependencies": { + "is-network-error": "^1.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver": { + "version": "7.8.4", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/stdin-discarder": { + "version": "0.3.2", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/stdin-discarder/-/stdin-discarder-0.3.2.tgz", + "integrity": "sha512-eCPu1qRxPVkl5605OTWF8Wz40b4Mf45NY5LQmVPQ599knfs5QhASUm9GbJ5BDMDOXgrnh0wyEdvzmL//YMlw0A==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width": { + "version": "8.2.1", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/string-width/-/string-width-8.2.1.tgz", + "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", + "dependencies": { + "get-east-asian-width": "^1.5.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/undici": { + "version": "7.27.2", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/undici/-/undici-7.27.2.tgz", + "integrity": "sha512-uZsKNuzQxDMUY6M3pIMvy5tvlGmtq8XJ2oLAkfRKGNu+1VQAIvLy2xIVG5ATZl5wDXl/tddByAWCizRbOme+TA==", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.2", + "resolved": "https://prompt-security-443370709039.d.codeartifact.eu-north-1.amazonaws.com/npm/npm-proxy/yoctocolors/-/yoctocolors-2.1.2.tgz", + "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/.github/clawhub-cli/package.json b/.github/clawhub-cli/package.json new file mode 100644 index 0000000..15ece4d --- /dev/null +++ b/.github/clawhub-cli/package.json @@ -0,0 +1,8 @@ +{ + "name": "clawhub-cli-pin", + "private": true, + "description": "Pins the clawhub CLI used by skill-release.yml; package-lock.json provides the integrity hashes. Bump the version here and regenerate the lockfile with: npm install --package-lock-only", + "dependencies": { + "clawhub": "0.7.0" + } +} diff --git a/.github/workflows/skill-release.yml b/.github/workflows/skill-release.yml index ce3115c..c6c0942 100644 --- a/.github/workflows/skill-release.yml +++ b/.github/workflows/skill-release.yml @@ -19,8 +19,8 @@ on: permissions: read-all -env: - CLAWHUB_CLI_VERSION: 0.7.0 +# The clawhub CLI version is pinned (with integrity hashes) in +# .github/clawhub-cli/package-lock.json — bump it there. concurrency: group: skill-release-${{ github.ref }} @@ -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,51 +1708,12 @@ jobs: - name: Install clawhub CLI if: needs.release-tag.outputs.publish_clawhub == 'true' && env.CLAWHUB_TOKEN != '' - run: npm install -g clawhub@${CLAWHUB_CLI_VERSION} + 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 { execSync } = require("node:child_process"); - const fs = require("node:fs"); - const path = require("node:path"); - - const npmRoot = execSync("npm root -g", { encoding: "utf8" }).trim(); - 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 != '' @@ -1830,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 @@ -1894,50 +1863,11 @@ jobs: run: node scripts/ci/validate_skill_install_docs.mjs --skills "${{ steps.parse.outputs.skill_path }}" - name: Install clawhub CLI - run: npm install -g clawhub@${CLAWHUB_CLI_VERSION} + 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 { execSync } = require("node:child_process"); - const fs = require("node:fs"); - const path = require("node:path"); - - const npmRoot = execSync("npm root -g", { encoding: "utf8" }).trim(); - 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: | diff --git a/scripts/ci/install_clawhub_cli.sh b/scripts/ci/install_clawhub_cli.sh new file mode 100644 index 0000000..d656083 --- /dev/null +++ b/scripts/ci/install_clawhub_cli.sh @@ -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 diff --git a/scripts/ci/patch_clawhub_publish_payload.mjs b/scripts/ci/patch_clawhub_publish_payload.mjs new file mode 100644 index 0000000..ee962c8 --- /dev/null +++ b/scripts/ci/patch_clawhub_publish_payload.mjs @@ -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}`); diff --git a/scripts/test-skill-release-workflow.mjs b/scripts/test-skill-release-workflow.mjs index 7b105bc..636f368 100644 --- a/scripts/test-skill-release-workflow.mjs +++ b/scripts/test-skill-release-workflow.mjs @@ -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/,