Wso2 porting skill
Skill Chamal1120/apim-automated-patch-porting/porting-skill/wso2-porting-skill
Automation workflows for patch porting in APIM repos
npx -y skills add Chamal1120/apim-automated-patch-porting --skill wso2-porting-skillAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
A portable skill for porting a WSO2 PR to a target branch. Compatible with Claude Code, GitHub Copilot (agent mode), and Codex CLI.
SKILL.md
11.2 KB, ~2.9k tokens by cl100k_base, as published. Nobody here has run it
wso2-porting-skill
A portable skill for porting a WSO2 PR to a target branch. Compatible with Claude Code, GitHub Copilot (agent mode), and Codex CLI.
Trigger
This skill accepts two input forms — detect which one was used and extract variables accordingly:
Form A — by PR number:
"Port PR #<number> to <branch> using wso2-porting-skill"
- Extract:
PR_NUMBER,TARGET_BRANCH MERGE_COMMITmust be resolved from git log in step 1
Form B — by merge commit hash:
"Port PR in merge commit <commit-hash> to <branch> using wso2-porting-skill"
- Extract:
MERGE_COMMIT,TARGET_BRANCH PR_NUMBERmust be resolved from the commit message or MCP in step 1
Execute all steps below fully autonomously — no further prompts to the user.
Prerequisites
This skill requires the GitHub MCP server or a GITHUB_TOKEN environment variable
for the curl fallback. Setup instructions per tool:
| Tool | MCP setup |
|---|---|
| Claude Code | claude mcp add --transport http github https://api.githubcopilot.com/mcp -H "Authorization: Bearer YOUR_PAT" |
| GitHub Copilot | Built-in — enable in repo Settings → Copilot → Coding agent → MCP configuration |
| Codex CLI | Add to ~/.codex/config.toml — see block below |
# ~/.codex/config.toml (Codex CLI)
[mcp_servers.github]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
enabled = true
[mcp_servers.github.env]
GITHUB_PERSONAL_ACCESS_TOKEN = "${GITHUB_TOKEN}"
Steps
1. Resolve the feature commit
The resolution path depends on which input form was used:
If Form A (PR number was given) — resolve MERGE_COMMIT first:
# Find the merge commit on master/main that references this PR number
MERGE_COMMIT=$(git log --all --merges --oneline --grep="#${PR_NUMBER}" | head -1 | awk '{print $1}')
# Verify it was found
[ -z "$MERGE_COMMIT" ] && { echo "ERROR: no merge commit found for PR #${PR_NUMBER}"; exit 1; }
If Form B (merge commit hash was given) — resolve PR_NUMBER first:
# PR number is usually in the merge commit subject, e.g. "Merge pull request #1234 from ..."
MERGE_COMMIT=<user-provided-hash>
PR_NUMBER=$(git log -1 --pretty="%s" $MERGE_COMMIT | grep -oE '#[0-9]+' | head -1 | tr -d '#')
# If not found in commit message, it will be fetched via MCP/curl in step 2
Then for both forms — extract the actual feature commit:
# The feature branch tip is always the second parent of the merge commit
FEATURE_COMMIT=$(git log --merges -1 --pretty="%P" $MERGE_COMMIT | awk '{print $2}')
[ -z "$FEATURE_COMMIT" ] && { echo "ERROR: could not resolve feature commit from $MERGE_COMMIT"; exit 1; }
- Use
$FEATURE_COMMITfor all subsequent diff, cherry-pick, and file-scope operations. - Never use
$MERGE_COMMITdirectly — its diff spans both parents and produces a bloated, incorrect changeset.
2. Fetch PR and issue details
PR title, description, and linked issues are critical context for understanding the intent of the change — especially when cherry-pick fails and manual porting is needed.
Primary: use GitHub MCP server if available
Use the get_pull_request tool from the GitHub MCP server to fetch:
- PR title, body, and number
- Any linked issue numbers mentioned in the body
Then use get_issue for each linked issue to fetch full issue context.
Keep all of this in memory throughout the porting process.
Fallback: use curl if MCP is unavailable or fails
Detect MCP availability by attempting the call. If it errors or times out, fall back to curl automatically — do not stop and ask the user.
# Set these from environment or ask the user once if missing
GITHUB_TOKEN="${GITHUB_TOKEN}"
REPO=$(git remote get-url origin | sed 's/.*github.com[:/]//' | sed 's/\.git//')
# Fetch PR details
PR_JSON=$(curl -sf \
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${REPO}/pulls/${PR_NUMBER}")
PR_TITLE=$(echo "$PR_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin)['title'])" 2>/dev/null)
PR_BODY=$(echo "$PR_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin)['body'])" 2>/dev/null)
# Extract linked issue numbers from body (matches #123 patterns)
ISSUE_NUMBERS=$(echo "$PR_BODY" | grep -oE '#[0-9]+' | tr -d '#')
# Fetch each linked issue
for ISSUE in $ISSUE_NUMBERS; do
curl -sf \
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${REPO}/issues/${ISSUE}"
done
If GITHUB_TOKEN is also unavailable, attempt an unauthenticated call (works for
public repos, rate-limited to 60/hr):
curl -sf \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${REPO}/pulls/${PR_NUMBER}"
If all fetch methods fail, log a warning and continue — do not abort. The git history and commit message will be used as context instead.
3. Set up isolated worktree
By this point PR_NUMBER must be known — it was either provided directly (Form A) or
resolved from the commit message or MCP in step 2 (Form B). If it is still unknown,
use the short merge commit hash as a fallback identifier: PR_ID=${PR_NUMBER:-${MERGE_COMMIT:0:8}}.
TIMESTAMP=$(date +%s)
PR_ID=${PR_NUMBER:-${MERGE_COMMIT:0:8}}
# Resolve to an absolute path — relative paths break when the agent shell resets
WORKTREE_DIR="$(cd .. && pwd)/porting-${TARGET_BRANCH}-${TIMESTAMP}"
git worktree add -b "port/${PR_ID}-to-${TARGET_BRANCH}" $WORKTREE_DIR $TARGET_BRANCH
cd $WORKTREE_DIR || { echo "ERROR: failed to enter worktree at $WORKTREE_DIR"; exit 1; }
# Verify we are on the correct branch before doing anything else
CURRENT=$(git branch --show-current)
EXPECTED="port/${PR_ID}-to-${TARGET_BRANCH}"
[ "$CURRENT" = "$EXPECTED" ] || { echo "ERROR: on branch '$CURRENT', expected '$EXPECTED'"; exit 1; }
echo "WORKTREE_DIR=${WORKTREE_DIR}" # Print so the value can be referenced in later steps
Critical — shell context persistence: Each tool call (
execute,terminal) may spawn a fresh shell, silently dropping any previouscd. Every command block from step 4 onwards must begin withcd $WORKTREE_DIRto re-enter the worktree explicitly. Never assume the working directory is preserved between steps.
4. Read source context
cd $WORKTREE_DIR || { echo "ERROR: lost worktree context"; exit 1; }
MAIN_GIT_DIR=$(git rev-parse --git-common-dir)
MAIN_REPO_ROOT=$(dirname $MAIN_GIT_DIR)
- Read source files from git history, not from disk:
cd $WORKTREE_DIR && git show $FEATURE_COMMIT:<relative/path/to/file> - Get the list of changed files:
cd $WORKTREE_DIR && git show $FEATURE_COMMIT --name-only - Identify structural mismatches:
- If a file in the commit does not exist in the worktree, search for it:
cd $WORKTREE_DIR && find . -name "*<filename>*" - Check for missing dependencies by diffing
pom.xml:cd $WORKTREE_DIR && git show $FEATURE_COMMIT:pom.xml > /tmp/source-pom.xml && diff /tmp/source-pom.xml pom.xml
- If a file in the commit does not exist in the worktree, search for it:
5. Contextual analysis
cd $WORKTREE_DIR && git show $FEATURE_COMMIT
cd $WORKTREE_DIR && find . -type f -name "*.java" | head -50
Cross-reference findings with the PR description and linked issue context fetched in step 2 to understand the intent behind each change — not just what changed, but why.
6. Surgical porting
Attempt cherry-pick first:
cd $WORKTREE_DIR && git cherry-pick $FEATURE_COMMIT
- If exit 0 → the port applied cleanly. Skip to step 7. Do NOT edit any additional files.
- If non-zero → abort and port manually:
cd $WORKTREE_DIR && git cherry-pick --abort
Manual porting rules (only on cherry-pick failure):
- Edit ONLY the files returned by
cd $WORKTREE_DIR && git show $FEATURE_COMMIT --name-only. No exceptions. - All file edits must be made inside
$WORKTREE_DIR, never in the main repo root. - Achieve the same logical outcome using the target branch's existing patterns.
- Use the PR description and issue context from step 2 to guide decisions when the target branch architecture differs from the source.
- For
pom.xml: add only the specific<dependency>block that is missing. Do NOT reformat, reorder, or upgrade versions of any existing entries.
7. Compile and verify
Initial build (--ntp suppresses download progress bars only — full build output still
appears on stdout and is fully readable for error diagnosis):
cd $WORKTREE_DIR && mvn clean install --ntp -T 1C \
-Dcheckstyle.skip=true \
-Dmaven.javadoc.skip=true \
-Dmaven.test.skip=true
- If no output appears for more than 5 minutes, kill the process and run
cd $WORKTREE_DIR && mvn dependency:resolveto diagnose network or dependency fetch issues. - Subsequent retry builds:
cd $WORKTREE_DIR && mvn install --ntp -T 1C \ -Dcheckstyle.skip=true \ -Dmaven.javadoc.skip=true \ -Dmaven.test.skip=true
8. Handle build results
If successful:
cd $WORKTREE_DIR && git commit -m "Port: ${PR_TITLE} (#${PR_ID}) to ${TARGET_BRANCH}"
- Do not push. Do not open a PR. Stop here.
- Print a clear summary — use the actual resolved
$WORKTREE_DIRvalue, not a placeholder:✓ Port complete Branch: port/<PR_ID>-to-<TARGET_BRANCH> Worktree: <actual absolute path of $WORKTREE_DIR> What was done: - <cherry-pick succeeded cleanly | manual porting was required> - <structural adaptations made, if any> - <pom.xml changes, if any> To push and open a PR, run: cd <actual absolute path of $WORKTREE_DIR> git push -u origin port/<PR_ID>-to-<TARGET_BRANCH>
If failed — retry up to 3 times, distinct strategy each attempt:
- Attempt 2: Re-read the full build log. Find the first
ERRORline. Fix only that. - Attempt 3: Check whether the error is in a dependency rather than changed files.
cd $WORKTREE_DIR && mvn dependency:tree 2>&1 | grep -iE "error|conflict|missing" - Attempt 4: Stop. Do not guess further. Print:
✗ Porting not possible after 3 build attempts. PR: #<PR_ID> → <TARGET_BRANCH> Reason: <exact first ERROR line from build log> Files changed: <list from git show --name-only> Suggested next step: <manual investigation hint based on error type>
Compatibility matrix
| Capability | Claude Code | GitHub Copilot | Codex CLI |
|---|---|---|---|
| GitHub MCP (PR/issue fetch) | Native | Native (agent mode) | Via config.toml |
| curl fallback | Yes | Yes | Yes |
| git + mvn commands | Yes | Yes | Yes |
| Auto-trigger on natural language | Yes | Yes | Yes |
| Skill file location | .claude/agents/ or .github/ | .github/ | .codex/ or .github/ |
Note on Codex CLI: There are known intermittent issues where MCP servers defined in
config.tomlfail to connect silently. The curl fallback in step 2 handles this automatically — no manual intervention needed.