name: 发布 skill # 推送与 v* 匹配的 annotated tag 时,将 skill/ 目录打包为 ZIP 文件,并发布到当前仓库的 Release。 # ZIP 根目录直接包含 SKILL.md;Release 正文使用 annotated tag message。 on: push: tags: - "v*" jobs: release: runs-on: ubuntu-latest permissions: contents: write steps: - name: 检出源代码 uses: actions/checkout@v4 with: fetch-depth: 0 - name: 读取版本说明并打包 skill id: pack run: | set -eu tag_ref="refs/tags/$GITHUB_REF_NAME" # actions/checkout may replace an annotated tag ref with its peeled commit # when a branch has the same name. Fetch the full tag ref again before # reading its object type and message. git fetch --force origin "$tag_ref:$tag_ref" object_type=$(git cat-file -t "$tag_ref") test "$object_type" = tag || { echo "发布 tag 必须是 annotated tag,当前对象类型:$object_type" exit 1 } git for-each-ref "$tag_ref" --format='%(contents)' > release-message.md test -s release-message.md || { echo "annotated tag message 为空" exit 1 } name=$(sed -n 's/^name:[[:space:]]*//p' skill/SKILL.md | head -1) test -n "$name" || { echo "无法从 skill/SKILL.md 读取 name 字段" exit 1 } (cd skill && zip -qr "../$name.zip" .) echo "name=$name" >> "$GITHUB_OUTPUT" echo "已生成 ZIP 文件:$name.zip" echo "ZIP 文件清单:" unzip -l "$name.zip" - name: 创建 Release 并上传附件 env: TOKEN: ${{ secrets.GITHUB_TOKEN }} API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }} TAG: ${{ github.ref_name }} ZIP: ${{ steps.pack.outputs.name }}.zip run: | set -eu payload=$(python3 - <<'PY' import json import os from pathlib import Path print(json.dumps({ "tag_name": os.environ["TAG"], "name": os.environ["TAG"], "body": Path("release-message.md").read_text(encoding="utf-8").rstrip(), })) PY ) response=$(curl -fsS -X POST "$API/releases" \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ -d "$payload") id=$(printf '%s' "$response" | python3 -c 'import json, sys; print(json.load(sys.stdin)["id"])') curl -fsS -X POST "$API/releases/$id/assets?name=$ZIP" \ -H "Authorization: token $TOKEN" \ -F "attachment=@$ZIP" echo "已发布 Release:$TAG" echo "已上传附件:$ZIP"