name: 'Register Skill' description: 'Standardized registration of a skill version to the business system' inputs: client_key: description: 'Authentication key for the business system' required: true api_base: description: 'API gateway base URL' default: 'https://api-gw-test.yuanwei-lnc.com' skill_slug: description: 'Override skill slug (defaults to package.json name or repo name)' required: false release_note: description: 'Optional release note for this version' required: false default: '' runs: using: "composite" steps: - 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: | import os, json, sys from urllib.request import urlopen, Request from urllib.error import HTTPError 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('/') base_dir = subpath if subpath else '.' # 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] # 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) 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 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) # 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)