From be6ed16735304aebb1244697038261c9115744a6 Mon Sep 17 00:00:00 2001 From: ivanberry Date: Thu, 12 Mar 2026 22:10:16 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20rewrite=20in=20pure=20Python=20stdlib?= =?UTF-8?q?=20=E2=80=94=20no=20apt-get,=20no=20jq,=20no=20curl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- register-skill/action.yaml | 191 +++++++++++++++---------------------- 1 file changed, 75 insertions(+), 116 deletions(-) diff --git a/register-skill/action.yaml b/register-skill/action.yaml index 26e4ad3..aa227f5 100644 --- a/register-skill/action.yaml +++ b/register-skill/action.yaml @@ -19,134 +19,93 @@ inputs: runs: using: "composite" steps: - - name: Install runtime dependencies - shell: bash - run: | - set -e - MISSING="" - command -v jq >/dev/null 2>&1 || MISSING="$MISSING jq" - command -v curl >/dev/null 2>&1 || MISSING="$MISSING curl" - command -v python3 >/dev/null 2>&1 || MISSING="$MISSING python3" - if [ -n "$MISSING" ]; then - apt-get update -qq - apt-get install -y -qq $MISSING ca-certificates - else - echo "All dependencies already available, skipping install" - fi - - - name: Load skill doc - shell: bash - env: - SKILL_SUBPATH: ${{ env.SKILL_SUBPATH }} - SKILL_DOC_PATH: ${{ env.SKILL_DOC_PATH }} - run: | - set -euo pipefail - DOC_PATH="${SKILL_DOC_PATH:-SKILL.md}" - BASE="${SKILL_SUBPATH:+$SKILL_SUBPATH/}" - ABS="${BASE}${DOC_PATH}" - - if [ ! -f "$ABS" ]; then - FALLBACK="${BASE}README.md" - if [ -f "$FALLBACK" ]; then - ABS="$FALLBACK" - DOC_PATH="README.md" - else - echo "ERROR: skill doc not found at $ABS" - exit 1 - fi - fi - - echo "Using doc: $ABS" - jq -Rs . < "$ABS" > /tmp/skill_doc.json - echo "RESOLVED_DOC_PATH=$DOC_PATH" >> "$GITHUB_ENV" - - - name: Register version - shell: bash + - name: Register skill version + shell: python3 {0} env: INPUT_CLIENT_KEY: ${{ inputs.client_key }} INPUT_API_BASE: ${{ inputs.api_base }} INPUT_SKILL_SLUG: ${{ inputs.skill_slug }} INPUT_RELEASE_NOTE: ${{ inputs.release_note }} SKILL_SUBPATH: ${{ env.SKILL_SUBPATH }} + SKILL_DOC_PATH: ${{ env.SKILL_DOC_PATH }} + GITHUB_REPOSITORY: ${{ github.repository }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SHA: ${{ github.sha }} + GITHUB_SERVER_URL: ${{ github.server_url }} run: | - set -euo pipefail + import os, json, sys + from urllib.request import urlopen, Request + from urllib.error import HTTPError - # Resolve slug: input → package.json → pyproject.toml → repo name - SLUG="${INPUT_SKILL_SLUG:-}" - BASE_DIR="${SKILL_SUBPATH:-.}" + api_base = os.environ['INPUT_API_BASE'].rstrip('/') + client_key = os.environ['INPUT_CLIENT_KEY'] + skill_slug = os.environ.get('INPUT_SKILL_SLUG', '').strip() + release_note = os.environ.get('INPUT_RELEASE_NOTE', '') + subpath = os.environ.get('SKILL_SUBPATH', '').strip() + doc_path = os.environ.get('SKILL_DOC_PATH', '').strip() or 'SKILL.md' + repo = os.environ['GITHUB_REPOSITORY'] + ref_name = os.environ['GITHUB_REF_NAME'] + sha = os.environ['GITHUB_SHA'] + server_url = os.environ['GITHUB_SERVER_URL'].rstrip('/') - if [ -z "$SLUG" ] && [ -f "${BASE_DIR}/package.json" ]; then - SLUG=$(jq -r '.name // empty' "${BASE_DIR}/package.json" | sed 's|.*/||') - fi + base_dir = subpath if subpath else '.' - if [ -z "$SLUG" ] && [ -f "${BASE_DIR}/pyproject.toml" ]; then - SLUG=$(python3 -c " - import sys, tomllib - d = tomllib.load(open(sys.argv[1],'rb')) - print((d.get('project',{}).get('name') or d.get('tool',{}).get('poetry',{}).get('name') or '')) - " "${BASE_DIR}/pyproject.toml" 2>/dev/null || true) - SLUG="${SLUG##*/}" - fi + # Resolve skill slug + if not skill_slug: + pkg = os.path.join(base_dir, 'package.json') + if os.path.exists(pkg): + name = json.load(open(pkg)).get('name', '') + skill_slug = name.split('/')[-1] if name else '' + if not skill_slug: + skill_slug = repo.split('/')[-1] - if [ -z "$SLUG" ]; then - SLUG="${GITHUB_REPOSITORY##*/}" - fi + # Load skill doc + doc_abs = os.path.join(subpath, doc_path) if subpath else doc_path + if not os.path.exists(doc_abs): + fallback = os.path.join(subpath, 'README.md') if subpath else 'README.md' + if os.path.exists(fallback): + doc_abs = fallback + doc_path = 'README.md' + else: + print(f'ERROR: skill doc not found: {doc_abs}', flush=True) + sys.exit(1) + doc_content = open(doc_abs).read() + print(f'Registering slug={skill_slug} version={ref_name} doc={doc_abs}', flush=True) - echo "Registering slug=$SLUG version=${GITHUB_REF_NAME}" + def post(url, body, token=None): + headers = {'Content-Type': 'application/json'} + if token: + headers['Authorization'] = f'Bearer {token}' + req = Request(url, data=json.dumps(body).encode(), headers=headers, method='POST') + try: + with urlopen(req) as r: + return r.status, json.loads(r.read()) + except HTTPError as e: + return e.code, json.loads(e.read()) # Exchange client key for access token - SESSION_RES=$(curl -fsS -X POST "${INPUT_API_BASE}/auth/skill-credit/session" \ - -H "Content-Type: application/json" \ - -d "{\"clientKey\":\"${INPUT_CLIENT_KEY}\"}") + status, resp = post(f'{api_base}/auth/skill-credit/session', {'clientKey': client_key}) + token = resp.get('accessToken', '') + if not token: + print(f'ERROR: failed to get access token (HTTP {status}): {resp}', flush=True) + sys.exit(1) - ACCESS_TOKEN=$(echo "$SESSION_RES" | jq -r '.accessToken // empty') - if [ -z "$ACCESS_TOKEN" ]; then - echo "ERROR: failed to get access token" - echo "$SESSION_RES" - exit 1 - fi - - # Build and POST registration payload - RUNTIME_META=$(jq -nc \ - --arg entry "${SKILL_SUBPATH:+$SKILL_SUBPATH/}scripts" \ - '{entry_hint: $entry, provider: "forgejo"}') - - jq -n \ - --arg slug "$SLUG" \ - --arg ver "${GITHUB_REF_NAME}" \ - --arg note "${INPUT_RELEASE_NOTE:-}" \ - --arg url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" \ - --arg sub "${SKILL_SUBPATH:-}" \ - --arg ref "${GITHUB_REF_NAME}" \ - --arg sha "${GITHUB_SHA}" \ - --arg doc_p "${RESOLVED_DOC_PATH:-SKILL.md}" \ - --slurpfile doc_c /tmp/skill_doc.json \ - --argjson meta "$RUNTIME_META" \ - '{ - skill_slug: $slug, - version: $ver, - release_note: $note, - source_type: "git_ci", - repo_url: $url, - repo_subpath: $sub, - git_ref: $ref, - commit_sha: $sha, - skill_doc_path: $doc_p, - skill_doc_content: $doc_c[0], - runtime_meta: $meta - }' > /tmp/payload.json - - HTTP_CODE=$(curl -sS -o /tmp/register_response.json -w '%{http_code}' \ - -X POST "${INPUT_API_BASE}/ecom/skills/register-by-slug" \ - -H "Authorization: Bearer ${ACCESS_TOKEN}" \ - -H "Content-Type: application/json" \ - -d @/tmp/payload.json) - - if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then - echo "ERROR: registration failed HTTP $HTTP_CODE" - cat /tmp/register_response.json - exit 1 - fi - - echo "Registered successfully:" - cat /tmp/register_response.json + # Register + payload = { + 'skill_slug': skill_slug, + 'version': ref_name, + 'release_note': release_note, + 'source_type': 'git_ci', + 'repo_url': f'{server_url}/{repo}.git', + 'repo_subpath': subpath, + 'git_ref': ref_name, + 'commit_sha': sha, + 'skill_doc_path': doc_path, + 'skill_doc_content': doc_content, + 'runtime_meta': {'entry_hint': f'{subpath + "/" if subpath else ""}scripts', 'provider': 'forgejo'}, + } + status, resp = post(f'{api_base}/ecom/skills/register-by-slug', payload, token) + if not (200 <= status < 300): + print(f'ERROR: registration failed HTTP {status}: {resp}', flush=True) + sys.exit(1) + print(f'Registered successfully: {json.dumps(resp, indent=2)}', flush=True)