From 97f5c10a8ac35b80bc40f1fb8a6fdba16bd98d05 Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Tue, 25 Aug 2026 22:37:08 +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/pr.yml | 1 + README.md | 14 ++--- scripts/validate-readme-no-version.mjs | 78 ++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 scripts/validate-readme-no-version.mjs diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index d63535f..4ab064d 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -38,3 +38,4 @@ jobs: mise run build mise run pkgjsonlint mise run pack:check + PLUGIN_MANIFEST=package.json node scripts/validate-readme-no-version.mjs diff --git a/README.md b/README.md index 4bbd823..8c6423c 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Before installing, make sure you have: - **JFrog host** — A [JFrog Platform](https://jfrog.com) instance you can authenticate against, exposed to the plugin as `JFROG_PLATFORM_URL` (e.g. `mycompany.jfrog.io`). The JFrog Platform MCP server authenticates via OAuth (browser sign-in). - **OpenCode** — Installed (verified against OpenCode **1.17.7** and newer, which honors `config.skills.paths` in object form). - **Node.js** (≥ 18) — with `npx` on your `PATH` (used by the Agent Guard). -- **Skill runtime requirements** — `jf` CLI, `jq`, and `curl` on `PATH`, plus a configured JFrog CLI server. For the minimum versions, see the upstream skills [`Requirements`](https://github.com/jfrog/jfrog-skills/blob/v0.22.0/README.md#requirements). Configure the CLI with `jf login` / `jf config add` — see [Authentication](#authentication). +- **Skill runtime requirements** — `jf` CLI, `jq`, and `curl` on `PATH`, plus a configured JFrog CLI server. For the minimum versions, see the upstream skills [`Requirements`](https://github.com/jfrog/jfrog-skills/blob/main/README.md#requirements). Configure the CLI with `jf login` / `jf config add` — see [Authentication](#authentication). - **JFrog AI Catalog** (optional) — If you want to use the Agent Guard feature, your JFrog subscription needs to include the AI Catalog entitlement. Contact your JFrog account team if you're unsure whether it's enabled. - **JFrog CLI ≥ 2.105.0** (optional) — If you want the Agent Guard to auto-resolve the credentials/server ID from the JFrog CLI configuration. - **JFrog project** (optional) — If you want to use the Agent Guard feature. @@ -214,7 +214,7 @@ The `skills/` tree is vendored from [`jfrog/jfrog-skills`](https://github.com/jfrog/jfrog-skills) at the version pinned in [`sync-skills-vendor.json`](sync-skills-vendor.json). To pull a newer upstream release: -1. Bump `pin` in `sync-skills-vendor.json` to the new tag (e.g. `v0.23.0`). +1. Bump `pin` in `sync-skills-vendor.json` to the new upstream tag. 2. Re-sync and commit the refreshed tree: ```bash @@ -223,9 +223,7 @@ The `skills/` tree is vendored from It downloads the pinned tarball from `codeload.github.com` and replaces the directories listed in `paths` (today: `skills/`). -3. Update the pinned-version link in the [Prerequisites](#prerequisites) section so the - skill runtime requirements point at the new tag. -4. Cut a plugin release so the new skills ship to users (see [Release](#release)). +3. Cut a plugin release so the new skills ship to users (see [Release](#release)). Until a release is published, installed plugins keep using the previously vendored skills. @@ -234,13 +232,13 @@ CI runs `mise run sync-skills:check`, which re-vendors and fails if the committe --- -## Upgrading from < 0.0.3 +## Upgrading from legacy skill layout This release changes behavior in ways that are **not** backward compatible: - **Skill catalog changed.** The previous Artifactory skills — `skill-install`, `skill-publish`, `jfrog-cli`, `opencode-jfrog-mcp`, `jfrog-curation`, `jfrog-packages` — are replaced by the canonical vendored skills above. Invocations of the removed skill names no longer exist; that functionality now folds into the `jfrog` skill. -- **Package-manager auto-setup was removed.** Earlier versions ran `jf setup ` automatically on session start; that is gone. Durable package-manager setup is provided by the `jfrog-setup-package-managers` skill. -- **Old skills are not auto-cleaned.** The plugin no longer touches `~/.config/opencode/skills`. If you used a version < 0.0.3, remove the old managed skill directories yourself under `~/.config/opencode/skills`. +- **Package-manager auto-setup was removed.** Earlier releases ran `jf setup ` automatically on session start; that is gone. Durable package-manager setup is provided by the `jfrog-setup-package-managers` skill. +- **Old skills are not auto-cleaned.** The plugin no longer touches `~/.config/opencode/skills`. If you used a legacy release with runtime-managed skills, remove the old managed skill directories yourself under `~/.config/opencode/skills`. - **No more runtime artifacts.** The plugin no longer injects instructions files or writes local package-manager state, and it no longer downloads skills at runtime. - **Dependencies resolve from public npm.** Internal registry references were removed; the build and CI now resolve from public npm. 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 110acb88b30f4204c02bb64f65fc4f42dfbff007 Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Mon, 31 Aug 2026 23:57:16 +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/pr.yml | 1 - VENDOR.md | 13 +++-- scripts/validate-readme-no-version.mjs | 78 -------------------------- 3 files changed, 7 insertions(+), 85 deletions(-) delete mode 100644 scripts/validate-readme-no-version.mjs diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 4ab064d..d63535f 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -38,4 +38,3 @@ jobs: mise run build mise run pkgjsonlint mise run pack:check - PLUGIN_MANIFEST=package.json node scripts/validate-readme-no-version.mjs diff --git a/VENDOR.md b/VENDOR.md index 1a2af46..e9fe562 100644 --- a/VENDOR.md +++ b/VENDOR.md @@ -15,7 +15,7 @@ The vendoring source is declared in `sync-skills-vendor.json` at the repo root: ```json { "repo": "jfrog/jfrog-skills", - "pin": "v0.22.0", + "pin": "", "paths": ["skills"] } ``` @@ -23,7 +23,7 @@ The vendoring source is declared in `sync-skills-vendor.json` at the repo root: | Field | Meaning | | ------- | ------------------------------------------------------------------------------------------- | | `repo` | The upstream GitHub repository (`owner/name`) to vendor from. | -| `pin` | The exact upstream ref to vendor (a tag, e.g. `v0.16.0`). Pin to a tag for reproducibility. | +| `pin` | The exact upstream release tag to vendor. Pin to a tag for reproducibility. | | `paths` | The paths within the upstream repo to copy into this repo root. Currently just `skills`. | ## How the sync works @@ -47,14 +47,15 @@ skills/ ``` > **Note:** the exact set of skill directories is whatever the pinned `jfrog/jfrog-skills` release -> ships under `skills/` — the sync copies the whole tree. `jfrog-mcp-management/` (JFrog Agent Guard -> MCP management, including the OpenCode harness) is included as of the pinned `v0.22.0`. +> ships under `skills/` — the sync copies the whole tree. + +The README deliberately omits release numbers. [`package.json`](package.json) and GitHub tags/releases are the authoritative plugin-version sources; `sync-skills-vendor.json` is the authoritative skills pin. The script is dependency-free Node ESM and makes no changes outside the vendored `paths`. ## Bumping the pin -1. Edit `sync-skills-vendor.json` and set `pin` to the new upstream tag (e.g. `v0.12.0`). +1. Edit `sync-skills-vendor.json` and set `pin` to the new upstream release tag. 2. Re-vendor: ```bash @@ -66,7 +67,7 @@ The script is dependency-free Node ESM and makes no changes outside the vendored ```bash git add sync-skills-vendor.json skills - git commit -m "feat(skills): vendor jfrog-skills@v0.12.0" + git commit -m "feat(skills): update vendored jfrog-skills" ``` 4. Cut a plugin release so the new skills ship to users. Until a release is published, installed plugins 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.");