From db5ea28b2519ab7d38ff62c4edb75d0a7a88807d Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Tue, 25 Aug 2026 22:37:09 +0300 Subject: [PATCH 1/2] AX-2170 - Remove plugin versions from READMEs Versions live in manifests, tags, and GitHub Releases. CI now fails if READMEs reintroduce version strings. Co-authored-by: Cursor --- .github/workflows/validate-version.yml | 5 ++ scripts/validate-readme-no-version.mjs | 78 ++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 scripts/validate-readme-no-version.mjs diff --git a/.github/workflows/validate-version.yml b/.github/workflows/validate-version.yml index 0449104..a8da198 100644 --- a/.github/workflows/validate-version.yml +++ b/.github/workflows/validate-version.yml @@ -25,3 +25,8 @@ jobs: exit 1 fi echo "Versions consistent: $VERSION" + + - name: Validate README has no plugin version + env: + PLUGIN_MANIFEST: plugin/.claude-plugin/plugin.json + run: node scripts/validate-readme-no-version.mjs diff --git a/scripts/validate-readme-no-version.mjs b/scripts/validate-readme-no-version.mjs new file mode 100644 index 0000000..513ce95 --- /dev/null +++ b/scripts/validate-readme-no-version.mjs @@ -0,0 +1,78 @@ +#!/usr/bin/env node + +// Copyright (c) JFrog Ltd. 2026 +// Licensed under the Apache License, Version 2.0 +// https://www.apache.org/licenses/LICENSE-2.0 + +import { readFileSync, existsSync } from "node:fs"; +import process from "node:process"; + +const docPaths = (process.env.DOCS || process.env.README_PATH || "README.md") + .split(/\s+/) + .filter(Boolean); + +const errors = []; + +for (const docPath of docPaths) { + const content = readFileSync(docPath, "utf8"); + validateDoc(docPath, content, errors); +} + +function validateDoc(docPath, content, errors) { + +const bannedPatterns = [ + { + re: /current version/i, + msg: 'README must not include a "Current version" callout — use GitHub Releases/tags.', + }, + { + re: /^## Versioning\s*$/m, + msg: 'README must not include a "## Versioning" section — versions live in the manifest and GitHub Releases.', + }, + { + re: /then tag \(for example `v/i, + msg: "README must not include example release tags.", + }, + { + re: /github\.com\/jfrog\/jfrog-skills\/blob\/v\d+\.\d+\.\d+/i, + msg: "README must not pin jfrog-skills doc links to a release tag — use main README or sync-skills-vendor.json.", + }, + { + re: /codeload\.github\.com\/jfrog\/jfrog-skills\/(tar\.gz|zip)\/v\d+\.\d+\.\d+/i, + msg: "README must not embed jfrog-skills release tags in download URLs.", + }, +]; + + for (const { re, msg } of bannedPatterns) { + if (re.test(content)) { + errors.push(`${docPath}: ${msg}`); + } + } + + const manifestPath = process.env.PLUGIN_MANIFEST; + if (docPath.endsWith("README.md") && manifestPath && existsSync(manifestPath)) { + let version; + if (manifestPath.endsWith(".json")) { + version = JSON.parse(readFileSync(manifestPath, "utf8")).version; + } else if (manifestPath.endsWith("gradle.properties")) { + const match = readFileSync(manifestPath, "utf8").match(/^version\s*=\s*(.+)$/m); + version = match?.[1]?.trim(); + } + + if (version && content.includes(version)) { + errors.push( + `${docPath}: contains plugin version "${version}" — authoritative source is ${manifestPath}.` + ); + } + } +} + +if (errors.length > 0) { + console.error("README version validation failed:"); + for (const error of errors) { + console.error(`- ${error}`); + } + process.exit(1); +} + +console.log("README version validation passed."); From 55f6cd01a99f26816562bfea2ba6a7c2c2f7ecd0 Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Mon, 31 Aug 2026 23:57:17 +0300 Subject: [PATCH 2/2] AX-2170 - Drop README version tests and leftover pin-sync machinery README prose checks are a maintenance trap. Vendor docs now name the authoritative pin and version sources. Co-authored-by: Cursor --- .github/workflows/validate-version.yml | 5 -- VENDOR.md | 17 ++++-- scripts/validate-readme-no-version.mjs | 78 -------------------------- 3 files changed, 11 insertions(+), 89 deletions(-) delete mode 100644 scripts/validate-readme-no-version.mjs diff --git a/.github/workflows/validate-version.yml b/.github/workflows/validate-version.yml index a8da198..0449104 100644 --- a/.github/workflows/validate-version.yml +++ b/.github/workflows/validate-version.yml @@ -25,8 +25,3 @@ jobs: exit 1 fi echo "Versions consistent: $VERSION" - - - name: Validate README has no plugin version - env: - PLUGIN_MANIFEST: plugin/.claude-plugin/plugin.json - run: node scripts/validate-readme-no-version.mjs diff --git a/VENDOR.md b/VENDOR.md index 356dd81..651cc38 100644 --- a/VENDOR.md +++ b/VENDOR.md @@ -13,10 +13,13 @@ version and committed to this repo. They are not downloaded or resolved at runtime. Because the skills are bundled, updating them requires a new plugin release — -there are no runtime skill updates. The skills are synced in on a `chore: -sync skills to vX.Y.Z` cadence (see recent commit history), which brings in -the latest pinned tag from `jfrog/jfrog-skills` and bumps the plugin version -accordingly. +there are no runtime skill updates. Skill-sync PRs bring in a pinned +`jfrog/jfrog-skills` release and bump the plugin version accordingly. + +The README deliberately omits release numbers. The `version` in +[`plugin/.claude-plugin/plugin.json`](plugin/.claude-plugin/plugin.json), +mirrored by [`marketplace.json`](marketplace.json), and GitHub tags/releases +are the authoritative plugin-version sources. ## Modules — vendored from `JFROG/jfrog-agent-hooks` @@ -32,8 +35,10 @@ verifies the committed tree matches the pin (see [`sync-modules-integrity.json`](.github/scripts/sync-modules-integrity.json) for the per-file checksums used in that check). -The current bundle uses `jfrog-agent-hooks/v0.11.1` as its base. Only upstream -`modules/` are vendored; upstream tests remain in the source repository. +The authoritative module release is the `pin` in +[`.github/scripts/sync-modules-vendor.json`](.github/scripts/sync-modules-vendor.json). +Only upstream `modules/` are vendored; upstream tests remain in the source +repository. ## Not vendored diff --git a/scripts/validate-readme-no-version.mjs b/scripts/validate-readme-no-version.mjs deleted file mode 100644 index 513ce95..0000000 --- a/scripts/validate-readme-no-version.mjs +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env node - -// Copyright (c) JFrog Ltd. 2026 -// Licensed under the Apache License, Version 2.0 -// https://www.apache.org/licenses/LICENSE-2.0 - -import { readFileSync, existsSync } from "node:fs"; -import process from "node:process"; - -const docPaths = (process.env.DOCS || process.env.README_PATH || "README.md") - .split(/\s+/) - .filter(Boolean); - -const errors = []; - -for (const docPath of docPaths) { - const content = readFileSync(docPath, "utf8"); - validateDoc(docPath, content, errors); -} - -function validateDoc(docPath, content, errors) { - -const bannedPatterns = [ - { - re: /current version/i, - msg: 'README must not include a "Current version" callout — use GitHub Releases/tags.', - }, - { - re: /^## Versioning\s*$/m, - msg: 'README must not include a "## Versioning" section — versions live in the manifest and GitHub Releases.', - }, - { - re: /then tag \(for example `v/i, - msg: "README must not include example release tags.", - }, - { - re: /github\.com\/jfrog\/jfrog-skills\/blob\/v\d+\.\d+\.\d+/i, - msg: "README must not pin jfrog-skills doc links to a release tag — use main README or sync-skills-vendor.json.", - }, - { - re: /codeload\.github\.com\/jfrog\/jfrog-skills\/(tar\.gz|zip)\/v\d+\.\d+\.\d+/i, - msg: "README must not embed jfrog-skills release tags in download URLs.", - }, -]; - - for (const { re, msg } of bannedPatterns) { - if (re.test(content)) { - errors.push(`${docPath}: ${msg}`); - } - } - - const manifestPath = process.env.PLUGIN_MANIFEST; - if (docPath.endsWith("README.md") && manifestPath && existsSync(manifestPath)) { - let version; - if (manifestPath.endsWith(".json")) { - version = JSON.parse(readFileSync(manifestPath, "utf8")).version; - } else if (manifestPath.endsWith("gradle.properties")) { - const match = readFileSync(manifestPath, "utf8").match(/^version\s*=\s*(.+)$/m); - version = match?.[1]?.trim(); - } - - if (version && content.includes(version)) { - errors.push( - `${docPath}: contains plugin version "${version}" — authoritative source is ${manifestPath}.` - ); - } - } -} - -if (errors.length > 0) { - console.error("README version validation failed:"); - for (const error of errors) { - console.error(`- ${error}`); - } - process.exit(1); -} - -console.log("README version validation passed.");