-
Notifications
You must be signed in to change notification settings - Fork 6
Add Braintree plugin publish skill #44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| --- | ||
| name: publish-braintree-plugin | ||
| description: >- | ||
| Publish @lambdacurry/medusa-payment-braintree to npm. Checks CHANGELOG coverage | ||
| of latest plugin changes, verifies the package version is bumped above the | ||
| published npm version, runs typecheck and Biome lint, then packs and publishes. | ||
| Use when the user asks to publish the Braintree plugin, release medusa-payment-braintree, | ||
| or ship a new Braintree package version. | ||
| disable-model-invocation: true | ||
| --- | ||
|
|
||
| # Publish Braintree Plugin | ||
|
|
||
| Publish `@lambdacurry/medusa-payment-braintree` from `plugins/braintree-payment`. | ||
|
|
||
| **Hard rule:** Do not pack or publish until every gate below passes. If a gate fails, stop, report what is missing, and wait for the user. Do not invent changelog entries or bump versions unless the user explicitly asks you to fix them. | ||
|
|
||
| Package root: `plugins/braintree-payment` | ||
| Package name: `@lambdacurry/medusa-payment-braintree` | ||
| Changelog: `plugins/braintree-payment/CHANGELOG.md` | ||
| Registry: always pass `--registry=https://registry.npmjs.org` on `npm whoami`, `npm view`, and `npm publish` (including dry-run). | ||
|
|
||
| ```text | ||
| Publish Progress: | ||
| - [ ] 1. Changelog covers latest plugin changes | ||
| - [ ] 2. Version bumped above npm | ||
| - [ ] 3. Typecheck passes | ||
| - [ ] 4. Lint passes | ||
| - [ ] 5. Pack succeeds | ||
| - [ ] 6. Publish succeeds | ||
| ``` | ||
|
|
||
| ## Gate 1 — Changelog covers latest changes | ||
|
|
||
| 1. Read `plugins/braintree-payment/package.json` and note `version` as `LOCAL_VERSION`. | ||
| 2. Read `plugins/braintree-payment/CHANGELOG.md`. The topmost `## X.Y.Z` section must equal `LOCAL_VERSION`. | ||
| 3. Find the previous changelog version header (the next `##` below the top). Call it `PREV_VERSION`. | ||
| 4. Require a clean plugin worktree before comparing history (pack/publish use the working tree): | ||
|
|
||
| ```bash | ||
| git status --short -- plugins/braintree-payment | ||
| ``` | ||
|
|
||
| **Fail** if any staged, unstaged, or untracked paths appear under `plugins/braintree-payment`. Summarize the dirty paths and stop. (Do not publish undocumented local edits.) | ||
|
|
||
| 5. Resolve `PREV_COMMIT` as the previous *release* boundary — the commit that **added** `PREV_VERSION` to `package.json`, not a later commit that removed it when bumping to `LOCAL_VERSION`. Fall back to the commit that introduced the `## PREV_VERSION` changelog header. | ||
|
|
||
| ```bash | ||
| # Prefer the commit that introduced PREV_VERSION in package.json (addition only). | ||
| PREV_COMMIT=$( | ||
| git log -S"\"version\": \"$PREV_VERSION\"" --diff-filter=A --format=%H -- \ | ||
| plugins/braintree-payment/package.json | tail -1 | ||
| ) | ||
|
|
||
| # Fallback: commit that introduced the PREV_VERSION changelog header. | ||
| if [ -z "$PREV_COMMIT" ]; then | ||
| PREV_COMMIT=$( | ||
| git log -S"## $PREV_VERSION" --diff-filter=A --format=%H -- \ | ||
| plugins/braintree-payment/CHANGELOG.md | tail -1 | ||
| ) | ||
| fi | ||
|
|
||
| if [ -z "$PREV_COMMIT" ]; then | ||
| echo "Could not resolve PREV_COMMIT for $PREV_VERSION" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| git log --oneline "${PREV_COMMIT}..HEAD" -- plugins/braintree-payment | ||
| git diff "${PREV_COMMIT}..HEAD" --stat -- plugins/braintree-payment | ||
| ``` | ||
|
|
||
| 6. Compare those commits/diffs to the `## LOCAL_VERSION` changelog section. | ||
| - User-facing fixes, improvements, breaking changes, and docs updates must appear. | ||
| - Ignore noise: lockfile-only, formatting-only, or leftover `.tgz` artifacts unless the release intentionally changes packaging. | ||
| 7. **Fail** if the top section is missing, mismatched, empty when there are meaningful changes, or omits notable behavior/API/packaging changes. Summarize the gaps and stop. | ||
|
|
||
| ## Gate 2 — Version is bumped | ||
|
|
||
| **Release policy** | ||
|
|
||
| - Stable `LOCAL_VERSION` (no `-` prerelease id): compare against the highest **stable** published version. Publish without a custom dist-tag (npm default `latest`). | ||
| - Prerelease `LOCAL_VERSION` (contains `-`, e.g. `0.2.0-next`): compare against the highest published version in the **same prerelease channel** (same suffix after `-`). Publish with `--tag <channel>` (e.g. `--tag next`). Never let a prerelease update `latest`. | ||
|
|
||
| 1. Read local version: | ||
|
|
||
| ```bash | ||
| node -p "require('./plugins/braintree-payment/package.json').version" | ||
| ``` | ||
|
|
||
| 2. Read the full published version list (not the `latest` dist-tag alone): | ||
|
|
||
| ```bash | ||
| npm view @lambdacurry/medusa-payment-braintree versions --json \ | ||
| --registry=https://registry.npmjs.org | ||
| ``` | ||
|
|
||
| 3. Filter that list per the release policy above, take the highest allowed published version as `HIGHEST_ALLOWED`, and **fail** unless `LOCAL_VERSION` is strictly greater (semver). | ||
| 4. Exact-version guard (separate from the highest-version check): | ||
|
|
||
| ```bash | ||
| npm view "@lambdacurry/medusa-payment-braintree@$LOCAL_VERSION" version \ | ||
| --registry=https://registry.npmjs.org | ||
| ``` | ||
|
|
||
| **Fail** if that command returns `LOCAL_VERSION` (already published). | ||
|
Comment on lines
+90
to
+105
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -u
file=".cursor/skills/publish-braintree-plugin/SKILL.md"
printf '%s\n' "== file status =="
git ls-files -- "$file"
printf '%s\n' "== lines 1-180 =="
sed -n '1,180p' "$file"
printf '%s\n' "== related references =="
rg -n -C 3 'npm view|versions --json|LOCAL_VERSION|HIGHEST_ALLOWED|set -e|exit status|not-found|not found|fail closed|registry' .cursor/skills .github 2>/dev/null || trueRepository: lambda-curry/medusa-plugins Length of output: 18124 🏁 Script executed: #!/bin/bash
set +e
pkg='`@lambdacurry/medusa-payment-braintree`'
missing='0.0.0-coderabbit-review-nonexistent'
run() {
label="$1"
shift
"$@" >/tmp/npm-review-out 2>/tmp/npm-review-err
status=$?
printf '\n== %s ==\nstatus=%s\nstdout=%s\nstderr=%s\n' \
"$label" "$status" "$(cat /tmp/npm-review-out)" "$(head -5 /tmp/npm-review-err)"
}
if command -v npm >/dev/null 2>&1; then
run "missing exact version" npm view "$pkg@$missing" version \
--registry=https://registry.npmjs.org
run "unreachable registry" npm view "$pkg@$missing" version \
--registry=http://127.0.0.1:1
else
printf 'npm is unavailable; no runtime probe executed\n'
fi
rm -f /tmp/npm-review-out /tmp/npm-review-errRepository: lambda-curry/medusa-plugins Length of output: 157 🌐 Web query:
💡 Result: When the npm CLI cannot find a requested package or specific version, it typically returns an exit code of 1 and an E404 error [1][2][3]. Key details regarding this behavior include: Exit Codes and Error Handling Historically, some versions of the npm CLI exhibited inconsistent behavior where certain "not found" scenarios would result in a zero exit code with no output [4][5][1]. However, modern versions of the npm CLI have been updated to ensure that requesting a non-existent package or a specific non-existent version correctly triggers an E404 error and a non-zero (1) exit code [1][2]. Common Causes for "Not Found" (E404) When you encounter an E404 error, it generally indicates that the registry does not contain the specified package or version [3]. Common causes include: - Incorrect Package Name: Typographical errors in the package name [3]. - Incorrect Registry Configuration: The npm CLI may be pointing to a registry that does not host the package (e.g., a private registry instead of the public npm registry or a misconfigured scope) [3][6]. - Missing Version/Tag: The specific version or dist-tag requested does not exist [5][1][2]. - Unpublishing or Deletion: The package or specific version may have been unpublished or removed by the author [3]. - Temporary Registry Issues: Intermittent issues with the npm registry itself can occasionally cause valid packages to be reported as not found [7][8]. Troubleshooting Steps If you receive an E404 error for a package you believe should exist: 1. Verify Registry Settings: Run npm config get registry to ensure you are pointing to the intended registry (commonly https://registry.npmjs.org/) [6]. 2. Check Package Availability: Search the npm website directly to confirm the package and version exist [3]. 3. Check Network/Proxies: If in a corporate environment, verify if a proxy is interfering with registry requests [7]. 4. Retry: If the error seems sporadic, it may be a transient issue with the registry [7][8]. For further details, refer to the official npm documentation on common errors and the npm-view command [7][9]. Citations:
Fail closed on npm lookup errors. Handle the exit status of both 🧰 Tools🪛 SkillSpector (2.5.1)[warning] 130: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) 🤖 Prompt for AI Agents |
||
| 5. Confirm `CHANGELOG.md` top section matches `LOCAL_VERSION` (already required by Gate 1). | ||
|
|
||
| ## Gate 3 — Typecheck | ||
|
|
||
| From repo root: | ||
|
|
||
| ```bash | ||
| yarn workspace @lambdacurry/medusa-payment-braintree typecheck | ||
| ``` | ||
|
|
||
| **Fail** on any TypeScript error. Do not continue. | ||
|
|
||
| ## Gate 4 — Lint | ||
|
|
||
| Biome is the repo linter/formatter (`biome.json` at repo root). From repo root: | ||
|
|
||
| ```bash | ||
| yarn biome check plugins/braintree-payment/src | ||
| ``` | ||
|
|
||
| **Fail** on diagnostics. Do not auto-fix unless the user asks; if they ask, run `yarn biome check --write plugins/braintree-payment/src`, re-run check, then continue. | ||
|
|
||
| ## Gate 5 — Pack | ||
|
|
||
| `prepublishOnly` builds via `npx medusa plugin:build`, but **`npm pack` does not run `prepublishOnly`**. Build explicitly before packing. | ||
|
|
||
| From repo root: | ||
|
|
||
| ```bash | ||
| yarn workspace @lambdacurry/medusa-payment-braintree build | ||
| npm pack ./plugins/braintree-payment | ||
| ``` | ||
|
|
||
| Confirm the tarball is created and contains the built `.medusa/server` output that `files` includes: | ||
|
|
||
| ```bash | ||
| tar -tzf lambdacurry-medusa-payment-braintree-*.tgz | head -50 | ||
| tar -tzf lambdacurry-medusa-payment-braintree-*.tgz | grep -E '\.medusa/server/' | head -20 | ||
| ``` | ||
|
|
||
| **Fail** if `.medusa/server` paths are missing from the tarball. | ||
|
Comment on lines
+141
to
+146
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: sed -n '120,185p' .cursor/skills/publish-braintree-plugin/SKILL.mdRepository: lambda-curry/medusa-plugins Length of output: 2410 🏁 Script executed: printf '%s\n' '--- skill file ---'
sed -n '136,178p' .cursor/skills/publish-braintree-plugin/SKILL.md
printf '%s\n' '--- package metadata ---'
cat plugins/braintree-payment/package.json
printf '%s\n' '--- publish workflow references ---'
rg -n -C 5 'npm (pack|publish)|prepublishOnly|medusa plugin:build' .github plugins/braintree-payment/package.json
printf '%s\n' '--- deterministic shell behavior ---'
python3 - <<'PY'
import subprocess
for command in [
"printf '%s\\n' absent | grep -E '\\.medusa/server/' | head -20",
"set -o pipefail; printf '%s\\n' absent | grep -E '\\.medusa/server/' | head -20",
]:
result = subprocess.run(["bash", "-c", command], text=True, capture_output=True)
print(f"{command}\nstatus={result.returncode}")
PYRepository: lambda-curry/medusa-plugins Length of output: 6019 Publish the exact tarball that you verify. The wildcard can select stale or multiple archives. Without 🧰 Tools🪛 SkillSpector (2.5.1)[warning] 130: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) 🤖 Prompt for AI Agents |
||
|
|
||
| Report the tarball name (e.g. `lambdacurry-medusa-payment-braintree-X.Y.Z.tgz`). | ||
|
|
||
| Do not commit generated `.tgz` files. | ||
|
|
||
| ## Gate 6 — Publish | ||
|
|
||
| Confirm npm auth before publishing: | ||
|
|
||
| ```bash | ||
| npm whoami --registry=https://registry.npmjs.org | ||
| ``` | ||
|
|
||
| If unauthenticated, stop and tell the user to log in (`npm login` or configure a token). Do not publish anonymously. | ||
|
|
||
| Publish the package directory (matches CI in `.github/workflows/publish.yml`). For prereleases, include `--tag <channel>` per the release policy: | ||
|
|
||
| ```bash | ||
| # Stable example: | ||
| npm publish ./plugins/braintree-payment --access public \ | ||
| --registry=https://registry.npmjs.org | ||
|
|
||
| # Prerelease example (0.2.0-next → tag next): | ||
| npm publish ./plugins/braintree-payment --access public --tag next \ | ||
| --registry=https://registry.npmjs.org | ||
|
Comment on lines
+164
to
+171
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- target skill context ---'
sed -n '130,225p' .cursor/skills/publish-braintree-plugin/SKILL.md
printf '%s\n' '--- workflow files ---'
git ls-files | rg '(^|/)\.github/workflows/|publish|braintree' | head -200
printf '%s\n' '--- publication-related references ---'
rg -n -C 4 --glob '*.yml' --glob '*.yaml' --glob '*.md' --glob '*.json' \
'npm (publish|pack|view)|--tag|dist-tag|braintree-payment|PREV_COMMIT|git log|git diff|npx' .Repository: lambda-curry/medusa-plugins Length of output: 11180 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- publish workflow ---'
cat -n .github/workflows/publish.yml
printf '%s\n' '--- npm configuration and publish references ---'
git ls-files | rg '(^|/)(\.npmrc|package\.json)$' | xargs -r -n1 sh -c 'echo "--- $0"; cat -n "$0"'
rg -n -C 5 'npm publish|--dry-run|--tag|dist-tag|publish' .github .cursor plugins/braintree-payment/package.json 2>/dev/null || true
printf '%s\n' '--- relevant history-independent file metadata ---'
git diff --stat
git status --shortRepository: lambda-curry/medusa-plugins Length of output: 37191 🌐 Web query:
💡 Result: By default, the npm publish command tags all published versions, including prerelease versions, with the latest distribution tag [1][2][3]. This behavior is the default behavior of the npm CLI unless the --tag option is explicitly provided during publication [1][2][4]. To avoid assigning the latest tag to a prerelease version, you must use the --tag flag to specify a different, non-latest tag [1][2]. Example of publishing a prerelease version without overwriting the latest tag: npm publish --tag beta In this example, the version will be tagged as beta instead of latest. When users run npm install <package_name> without a specific version or tag, npm will continue to install the version associated with the latest tag [5][2]. Official documentation indicates that this is intended behavior, though it is often noted by the community as a point of friction ("footgun") when developers inadvertently update the latest version for all users with a prerelease [6][3][7]. Projects typically use latest for stable releases and separate tags (e.g., beta, next, alpha) for unstable or prerelease versions to manage distribution effectively [1][2][8]. Citations:
🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re
skill = Path(".cursor/skills/publish-braintree-plugin/SKILL.md").read_text()
workflow = Path(".github/workflows/publish.yml").read_text()
publish_lines = [
line.strip()
for text in (skill, workflow)
for line in text.splitlines()
if re.search(r"\bnpm publish\b", line)
]
print("Publish commands:")
for line in publish_lines:
print(line)
print("\nExplicit-tag status:")
for line in publish_lines:
print(f"{'tag-present' if re.search(r'--tag(?:=|\s+)\S+', line) else 'tag-absent'}: {line}")
print("\nCurrent Braintree version:")
package = Path("plugins/braintree-payment/package.json").read_text()
match = re.search(r'"version"\s*:\s*"([^"]+)"', package)
print(match.group(1) if match else "not found")
assert "npm publish \"./$dir\" --access public" in workflow
assert "npm publish ./plugins/braintree-payment --access public \\" in skill
assert "--tag next" in skill
PYRepository: lambda-curry/medusa-plugins Length of output: 450 🏁 Script executed: #!/bin/bash
set -eu
python3 - <<'PY'
from pathlib import Path
import re
skill = Path(".cursor/skills/publish-braintree-plugin/SKILL.md").read_text()
workflow = Path(".github/workflows/publish.yml").read_text()
print("Skill publish blocks:")
for match in re.finditer(r"npm publish[^\n]*(?:\\\n[^\n]*)*", skill):
command = match.group(0).replace("\\\n", " ")
print(command)
print("\nWorkflow publish command:")
for line in workflow.splitlines():
if "npm publish" in line:
print(line.strip())
print("\nExplicit tag checks:")
commands = [
match.group(0).replace("\\\n", " ")
for match in re.finditer(r"npm publish[^\n]*(?:\\\n[^\n]*)*", skill)
]
commands += [line.strip() for line in workflow.splitlines() if "npm publish" in line]
for command in commands:
has_tag = bool(re.search(r"--tag(?:=|\s+)\S+", command))
print(("tag-present" if has_tag else "tag-absent") + ": " + command)
package = Path("plugins/braintree-payment/package.json").read_text()
version = re.search(r'"version"\s*:\s*"([^"]+)"', package).group(1)
print("\nCurrent Braintree version: " + version)
print("Current version is prerelease: " + str("-" in version))
assert "npm publish \"./$dir\" --access public" in workflow
assert any("--tag next" in command for command in commands)
assert "-next" in version
PYRepository: lambda-curry/medusa-plugins Length of output: 904 Make the dist-tag explicit on every publication path. Pass 🧰 Tools🪛 SkillSpector (2.5.1)[warning] 130: [RP1] null: npx commands without a version suffix (e.g. Remediation: Pin the version: npx (MCP Rug Pull (RP1)) 🤖 Prompt for AI Agents |
||
| ``` | ||
|
|
||
| Verify the **exact** version (not the `latest` dist-tag), with `--prefer-online` and bounded retries for registry propagation: | ||
|
|
||
| ```bash | ||
| LOCAL_VERSION="$(node -p "require('./plugins/braintree-payment/package.json').version")" | ||
| for i in 1 2 3 4 5; do | ||
| PUBLISHED="$( | ||
| npm view "@lambdacurry/medusa-payment-braintree@$LOCAL_VERSION" version \ | ||
| --registry=https://registry.npmjs.org \ | ||
| --prefer-online 2>/dev/null || true | ||
| )" | ||
| if [ "$PUBLISHED" = "$LOCAL_VERSION" ]; then | ||
| echo "Verified $LOCAL_VERSION on npm" | ||
| break | ||
| fi | ||
| if [ "$i" -eq 5 ]; then | ||
| echo "Timed out waiting for $LOCAL_VERSION on npm (last: ${PUBLISHED:-none})" >&2 | ||
| exit 1 | ||
| fi | ||
| sleep $((i * 3)) | ||
| done | ||
| ``` | ||
|
|
||
| ## Done report | ||
|
|
||
| After success, report: | ||
|
|
||
| - Published version and dist-tag used | ||
| - npm package URL: `https://www.npmjs.com/package/@lambdacurry/medusa-payment-braintree` | ||
| - Whether changelog/version gates were clean | ||
| - Typecheck/lint/pack/publish results | ||
| - Reminder: merging to `main` also triggers CI publish; if this version is already on npm, CI will skip it | ||
|
|
||
| ## Dry run | ||
|
|
||
| If the user asks for a dry run, complete Gates 1–5 only, then run: | ||
|
|
||
| ```bash | ||
| npm publish ./plugins/braintree-payment --access public --dry-run \ | ||
| --registry=https://registry.npmjs.org | ||
| ``` | ||
|
|
||
| For prerelease dry-runs, include the same `--tag <channel>` you would use for a real publish. | ||
|
|
||
| Do not publish for real. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major
Fix the
PREV_COMMITlookup.--diff-filter=Aselects commits where the file was added. It does not select a modifiedpackage.jsoncommit that adds the matching version line. Git defines-Sas an occurrence-count search andAas an added-path filter. A normal version bump therefore returns no commit for an existingpackage.json; the changelog fallback has the same defect.tail -1also selects the oldest result becausegit logis reverse chronological by default. (git-scm.com)Use a patch-aware search that identifies the commit adding the exact version line, then select the intended release boundary.
🧰 Tools
🪛 SkillSpector (2.5.1)
[warning] 130: [RP1] null: npx commands without a version suffix (e.g.
@1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.Remediation: Pin the version: npx
@scope/server@1.2.3(MCP Rug Pull (RP1))
🤖 Prompt for AI Agents