Publish hermes-skills-github via gitea-publish skill
This commit is contained in:
Executable
+66
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env bash
|
||||
# GitHub environment detection helper for Hermes Agent skills.
|
||||
#
|
||||
# Usage (via terminal tool):
|
||||
# source skills/github/github-auth/scripts/gh-env.sh
|
||||
#
|
||||
# After sourcing, these variables are set:
|
||||
# GH_AUTH_METHOD - "gh", "curl", or "none"
|
||||
# GITHUB_TOKEN - personal access token (set if method is "curl")
|
||||
# GH_USER - GitHub username
|
||||
# GH_OWNER - repo owner (only if inside a git repo with a github remote)
|
||||
# GH_REPO - repo name (only if inside a git repo with a github remote)
|
||||
# GH_OWNER_REPO - owner/repo (only if inside a git repo with a github remote)
|
||||
|
||||
# --- Auth detection ---
|
||||
|
||||
GH_AUTH_METHOD="none"
|
||||
GITHUB_TOKEN="${GITHUB_TOKEN:-}"
|
||||
GH_USER=""
|
||||
|
||||
if command -v gh &>/dev/null && gh auth status &>/dev/null 2>&1; then
|
||||
GH_AUTH_METHOD="gh"
|
||||
GH_USER=$(gh api user --jq '.login' 2>/dev/null)
|
||||
elif [ -n "$GITHUB_TOKEN" ]; then
|
||||
GH_AUTH_METHOD="curl"
|
||||
elif _hermes_env="${HERMES_HOME:-$HOME/.hermes}/.env"; [ -f "$_hermes_env" ] && grep -q "^GITHUB_TOKEN=" "$_hermes_env" 2>/dev/null; then
|
||||
GITHUB_TOKEN=$(grep "^GITHUB_TOKEN=" "$_hermes_env" | head -1 | cut -d= -f2 | tr -d '\n\r')
|
||||
if [ -n "$GITHUB_TOKEN" ]; then
|
||||
GH_AUTH_METHOD="curl"
|
||||
fi
|
||||
elif [ -f "$HOME/.git-credentials" ]; then
|
||||
GITHUB_TOKEN=$(uv run python3 "${HERMES_HOME:-$HOME/.hermes}/skills/github/github-auth/scripts/git-credential-token.py")
|
||||
if [ -n "$GITHUB_TOKEN" ]; then
|
||||
GH_AUTH_METHOD="curl"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Resolve username for curl method
|
||||
if [ "$GH_AUTH_METHOD" = "curl" ] && [ -z "$GH_USER" ]; then
|
||||
GH_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||
https://api.github.com/user 2>/dev/null \
|
||||
| python3 -c "import sys,json; print(json.load(sys.stdin).get('login',''))" 2>/dev/null)
|
||||
fi
|
||||
|
||||
# --- Repo detection (if inside a git repo with a GitHub remote) ---
|
||||
|
||||
GH_OWNER=""
|
||||
GH_REPO=""
|
||||
GH_OWNER_REPO=""
|
||||
|
||||
_remote_url=$(git remote get-url origin 2>/dev/null)
|
||||
if [ -n "$_remote_url" ] && echo "$_remote_url" | grep -q "github.com"; then
|
||||
GH_OWNER_REPO=$(echo "$_remote_url" | sed -E 's|.*github\.com[:/]||; s|\.git$||')
|
||||
GH_OWNER=$(echo "$GH_OWNER_REPO" | cut -d/ -f1)
|
||||
GH_REPO=$(echo "$GH_OWNER_REPO" | cut -d/ -f2)
|
||||
fi
|
||||
unset _remote_url
|
||||
|
||||
# --- Summary ---
|
||||
|
||||
echo "GitHub Auth: $GH_AUTH_METHOD"
|
||||
[ -n "$GH_USER" ] && echo "User: $GH_USER"
|
||||
[ -n "$GH_OWNER_REPO" ] && echo "Repo: $GH_OWNER_REPO"
|
||||
[ "$GH_AUTH_METHOD" = "none" ] && echo "⚠ Not authenticated — see github-auth skill"
|
||||
|
||||
export GH_AUTH_METHOD GITHUB_TOKEN GH_USER GH_OWNER GH_REPO GH_OWNER_REPO
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Print the first unambiguous GitHub token in a git credential-store file."""
|
||||
|
||||
from pathlib import Path
|
||||
import re
|
||||
import sys
|
||||
from urllib.parse import unquote, urlsplit
|
||||
|
||||
|
||||
_TOKEN_PREFIXES = ("ghp_", "github_pat_", "gho_", "ghu_", "ghs_", "ghr_")
|
||||
_INVALID_ESCAPE = re.compile(r"%(?![0-9A-Fa-f]{2})")
|
||||
|
||||
|
||||
def _decode(value: str | None) -> str:
|
||||
if value is None or _INVALID_ESCAPE.search(value):
|
||||
return ""
|
||||
decoded = unquote(value)
|
||||
if not decoded or any(ord(char) <= 0x1F or 0x7F <= ord(char) <= 0x9F for char in decoded):
|
||||
return ""
|
||||
return decoded
|
||||
|
||||
|
||||
def _token_from_url(line: str) -> str:
|
||||
if "\r" in line or "\n" in line:
|
||||
return ""
|
||||
try:
|
||||
credential = urlsplit(line)
|
||||
port = credential.port
|
||||
except ValueError:
|
||||
return ""
|
||||
if credential.scheme != "https" or credential.hostname != "github.com" or port not in (None, 443):
|
||||
return ""
|
||||
|
||||
username = _decode(credential.username)
|
||||
password = _decode(credential.password)
|
||||
if not username:
|
||||
return ""
|
||||
if password and password != "x-oauth-basic":
|
||||
return password
|
||||
if password == "x-oauth-basic":
|
||||
return username
|
||||
return username if username.startswith(_TOKEN_PREFIXES) else ""
|
||||
|
||||
|
||||
def main() -> int:
|
||||
path = Path(sys.argv[1]).expanduser() if len(sys.argv) > 1 else Path.home() / ".git-credentials"
|
||||
try:
|
||||
lines = path.read_bytes().split(b"\n")
|
||||
except OSError:
|
||||
return 1
|
||||
|
||||
for raw_line in lines:
|
||||
try:
|
||||
line = raw_line.decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
token = _token_from_url(line)
|
||||
if token:
|
||||
print(token)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user