mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-08-07 16:04:41 +08:00
chore: enhance skills validation and update workflows for npm publishing
This commit is contained in:
parent
a1ed6e21f2
commit
d2989fe74c
9
.github/workflows/release-skills.yml
vendored
9
.github/workflows/release-skills.yml
vendored
@ -6,6 +6,10 @@ on:
|
||||
paths: ['skills/**']
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
@ -39,7 +43,7 @@ jobs:
|
||||
|
||||
- name: Create Github Release
|
||||
id: release
|
||||
uses: ncipollo/release-action@v2
|
||||
uses: ncipollo/release-action@v1
|
||||
if: ${{ steps.changelog.outputs.skipped == 'false' }}
|
||||
with:
|
||||
name: "${{ steps.changelog.outputs.version }}"
|
||||
@ -53,6 +57,7 @@ jobs:
|
||||
skipIfReleaseExists: true
|
||||
|
||||
- name: Publish to npm
|
||||
id: publish
|
||||
if: ${{ steps.changelog.outputs.skipped == 'false' && steps.release.outputs.id != '' }}
|
||||
run: |
|
||||
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
|
||||
@ -61,7 +66,7 @@ jobs:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
- name: Notify cline-fork
|
||||
if: ${{ steps.changelog.outputs.skipped == 'false' }}
|
||||
if: ${{ steps.changelog.outputs.skipped == 'false' && steps.release.outputs.id != '' && steps.publish.outcome == 'success' }}
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.IDEE_GH_TOKEN }}
|
||||
|
||||
22
.github/workflows/validate-skills.yml
vendored
22
.github/workflows/validate-skills.yml
vendored
@ -9,8 +9,28 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- run: npm ci
|
||||
- run: npm run validate
|
||||
|
||||
- name: Detect changed skill directories
|
||||
id: changed-skills
|
||||
run: |
|
||||
# Collect top-level skill dirs touched by this PR (relative to skills/).
|
||||
# Passing explicit dirs means pre-existing nested skill categories
|
||||
# (to be flattened in a separate PR) don't block unrelated skill PRs.
|
||||
DIRS=$(git diff --name-only origin/${{ github.base_ref }}...HEAD \
|
||||
| grep '^skills/' \
|
||||
| cut -d'/' -f2 \
|
||||
| sort -u \
|
||||
| tr '\n' ' ')
|
||||
echo "dirs=$DIRS" >> $GITHUB_OUTPUT
|
||||
echo "Validating skill dirs: $DIRS"
|
||||
|
||||
- name: Validate changed skills
|
||||
run: npx tsx scripts/validate-skills.ts ${{ steps.changed-skills.outputs.dirs }}
|
||||
|
||||
@ -6,13 +6,17 @@
|
||||
"files": [
|
||||
"skills/"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tsx": "^4.21.0",
|
||||
"@salesforce/webapp-template-app-react-sample-b2e-experimental": "*",
|
||||
"@salesforce/webapp-template-app-react-sample-b2x-experimental": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"validate": "tsx scripts/validate-skills.ts",
|
||||
"validate:skills": "tsx scripts/validate-skills.ts",
|
||||
"sync-react-b2e-sample": "node scripts/sync-react-b2e-sample.js",
|
||||
"sync-react-b2x-sample": "node scripts/sync-react-b2x-sample.js"
|
||||
}
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
#!/usr/bin/env tsx
|
||||
// Validates the skills/ directory structure and SKILL.md format.
|
||||
// Exits with code 1 if any violations are found.
|
||||
//
|
||||
// Usage:
|
||||
// tsx scripts/validate-skills.ts # validate all skills
|
||||
// tsx scripts/validate-skills.ts apex-class # validate specific skill dirs
|
||||
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
@ -143,7 +147,10 @@ function parseFrontmatter(content: string): Record<string, string> | null {
|
||||
for (const line of match[1].split(/\r?\n/)) {
|
||||
const colonIdx = line.indexOf(":")
|
||||
if (colonIdx === -1) continue
|
||||
result[line.slice(0, colonIdx).trim()] = line.slice(colonIdx + 1).trim()
|
||||
const key = line.slice(0, colonIdx).trim()
|
||||
// Strip wrapping single or double quotes to match how consumers read values
|
||||
const raw = line.slice(colonIdx + 1).trim()
|
||||
result[key] = raw.replace(/^(['"])([\s\S]*)\1$/, "$2")
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -158,6 +165,10 @@ function getFrontmatterEnd(content: string): number {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function validateSkill(dirName: string, dirPath: string): string[] {
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
return [`skills/${dirName}: directory not found`]
|
||||
}
|
||||
|
||||
const errors: string[] = []
|
||||
|
||||
for (const check of STRUCTURE_CHECKS) {
|
||||
@ -182,13 +193,18 @@ function validateSkill(dirName: string, dirPath: string): string[] {
|
||||
}
|
||||
|
||||
function main(): void {
|
||||
const allErrors: string[] = []
|
||||
let checked = 0
|
||||
// If skill dir names are passed as arguments, validate only those.
|
||||
// Otherwise validate all entries in skills/.
|
||||
const targets = process.argv.slice(2)
|
||||
const entries = targets.length > 0 ? targets : fs.readdirSync(SKILLS_DIR)
|
||||
|
||||
for (const entry of fs.readdirSync(SKILLS_DIR)) {
|
||||
const allErrors: string[] = []
|
||||
let passed = 0
|
||||
|
||||
for (const entry of entries) {
|
||||
const entryErrors = validateSkill(entry, path.join(SKILLS_DIR, entry))
|
||||
allErrors.push(...entryErrors)
|
||||
if (entryErrors.length === 0) checked++
|
||||
if (entryErrors.length === 0) passed++
|
||||
}
|
||||
|
||||
if (allErrors.length > 0) {
|
||||
@ -199,7 +215,7 @@ function main(): void {
|
||||
console.error("")
|
||||
process.exit(1)
|
||||
} else {
|
||||
console.log(`Skill validation passed: ${checked} skill(s) checked.`)
|
||||
console.log(`Skill validation passed: ${passed} of ${entries.length} skill(s) checked.`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user