15 Commits

Author SHA1 Message Date
github-actions[bot]
4a00e65868 chore(registry): update latest core release to rel-v0.5.0 2026-05-11 03:00:38 +00:00
6c3c08b5d5 chore: unify workflows name style 2026-05-11 10:24:29 +08:00
ef5a332f17 chore(release): add partner core release workflow 2026-05-11 10:05:43 +08:00
github-actions[bot]
9acabca40e chore(registry): update latest buildable to buildable/0.5.0 2026-05-10 15:28:36 +00:00
b654090a6e feat(git): add latest buildable update workflow 2026-05-10 23:18:07 +08:00
github-actions[bot]
c9a7343b30 chore: update registry index 2026-05-10 14:27:29 +00:00
6250b480e0 chore: add onebot adapter registry manifest 2026-05-10 22:27:13 +08:00
github-actions[bot]
63e8cc314a chore: update registry index 2026-05-10 14:22:35 +00:00
451f83e14d fix(module-registry): resolve manifest paths from registry in index update script 2026-05-10 22:22:12 +08:00
2b7e6718d9 fix(git): stage registry/index.json in update workflow 2026-05-10 22:10:41 +08:00
ed806c668a feat(git): add module index updating workflow 2026-05-10 22:08:47 +08:00
da381c3adf refactor(partnerctl-module): add version attribute to manifest 2026-05-10 21:40:20 +08:00
1cbff98b36 chore(git): remove legacy gitea sync workflow 2026-05-10 21:36:12 +08:00
95a30f147c chore: add initial module registry structure 2026-05-10 21:32:06 +08:00
0ea8dfc7d9 fix(core): correct logback log level fallback syntax (#1) 2026-05-09 14:51:28 +08:00
10 changed files with 382 additions and 37 deletions

135
.github/workflows/release-core.yml vendored Normal file
View File

@@ -0,0 +1,135 @@
name: Release Partner Core
on:
workflow_dispatch:
inputs:
tag:
description: "Release tag, for example rel-v0.5.0"
required: true
type: string
push:
tags:
- "rel-v*"
permissions:
contents: write
jobs:
release-core:
runs-on: ubuntu-latest
steps:
- name: Resolve release metadata
id: release
shell: bash
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG="${{ inputs.tag }}"
else
TAG="${GITHUB_REF_NAME}"
fi
VERSION="${TAG#rel-v}"
ASSET_NAME="partner-core-${VERSION}.jar"
ASSET_URL="https://github.com/slhaf/Partner/releases/download/${TAG}/${ASSET_NAME}"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "asset_name=${ASSET_NAME}" >> "$GITHUB_OUTPUT"
echo "asset_url=${ASSET_URL}" >> "$GITHUB_OUTPUT"
echo "Release tag: ${TAG}"
echo "Release version: ${VERSION}"
echo "Release asset: ${ASSET_NAME}"
- name: Checkout release source
uses: actions/checkout@v4
with:
ref: ${{ steps.release.outputs.tag }}
- name: Set up Java 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
- name: Build Partner Core
run: |
mvn -B -DskipTests=true -pl Partner-Core -am package
- name: Prepare release artifact
shell: bash
run: |
mkdir -p dist
SOURCE_JAR="Partner-Core/target/partner-core-${{ steps.release.outputs.version }}.jar"
if [ ! -f "$SOURCE_JAR" ]; then
echo "Expected artifact not found: $SOURCE_JAR"
echo "Available Partner-Core target files:"
find Partner-Core/target -maxdepth 1 -type f -name "*.jar" -print
exit 1
fi
cp "$SOURCE_JAR" "dist/${{ steps.release.outputs.asset_name }}"
ls -lh dist
- name: Create GitHub Release
shell: bash
run: |
if gh release view "${{ steps.release.outputs.tag }}" >/dev/null 2>&1; then
echo "Release ${{ steps.release.outputs.tag }} already exists."
exit 1
fi
gh release create "${{ steps.release.outputs.tag }}" \
"dist/${{ steps.release.outputs.asset_name }}" \
--title "${{ steps.release.outputs.tag }}" \
--notes "Partner Core ${{ steps.release.outputs.version }}"
env:
GH_TOKEN: ${{ github.token }}
- name: Checkout master for registry update
uses: actions/checkout@v4
with:
ref: master
path: registry-worktree
- name: Update latestRelease
working-directory: registry-worktree
run: |
python3 - <<'PY'
import json
from pathlib import Path
version = "${{ steps.release.outputs.version }}"
url = "${{ steps.release.outputs.asset_url }}"
index_path = Path("registry/index.json")
index = json.loads(index_path.read_text(encoding="utf-8"))
index["partner"]["latestRelease"] = {
"url": url,
"version": version
}
index_path.write_text(
json.dumps(index, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8"
)
PY
- name: Commit registry update
working-directory: registry-worktree
run: |
if git diff --quiet registry/index.json; then
echo "No latestRelease changes."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add registry/index.json
git commit -m "chore(registry): update latest core release to ${{ steps.release.outputs.tag }}"
git push origin HEAD:master

View File

@@ -1,36 +0,0 @@
name: Sync from Gitea
# 1. 给 GITHUB_TOKEN 开写权限
permissions:
contents: write
on:
schedule:
- cron: '*/30 * * * *'
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: 配置 Git 用户
run: |
git config --global user.name "Gitea Sync Bot"
git config --global user.email "slhafzjw@slhaf.work"
- name: 关闭全局 SSL 校验
run: git config --global http.sslVerify false
- name: Clone from Gitea (mirror)
run: |
git clone --mirror \
https://${{ secrets.GITEA_USER }}:${{ secrets.GITEA_TOKEN }}@${{ secrets.GITEA_URL }} \
gitea-mirror
- name: Push to GitHub
run: |
cd gitea-mirror
# 明确推到名为 "github" 的 remote
git remote add github \
https://${{ github.repository_owner }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
git push --mirror github

View File

@@ -0,0 +1,70 @@
name: Update Latest Buildable
on:
workflow_dispatch:
inputs:
ref:
description: "Buildable ref, for example buildable/v0.5.0"
required: true
type: string
push:
tags:
- "buildable/*"
permissions:
contents: write
jobs:
update-latest-buildable:
runs-on: ubuntu-latest
steps:
- name: Resolve buildable ref
id: buildable
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "ref=${{ inputs.ref }}" >> "$GITHUB_OUTPUT"
else
echo "ref=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
fi
- name: Checkout master
uses: actions/checkout@v4
with:
ref: master
- name: Update latestBuildable
run: |
python3 - <<'PY'
import json
from pathlib import Path
ref = "${{ steps.buildable.outputs.ref }}"
index_path = Path("registry/index.json")
index = json.loads(index_path.read_text(encoding="utf-8"))
index["partner"]["latestBuildable"] = {
"url": "https://github.com/slhaf/Partner.git",
"ref": ref
}
index_path.write_text(
json.dumps(index, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8"
)
PY
- name: Commit registry update
run: |
if git diff --quiet registry/index.json; then
echo "No latestBuildable changes."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add registry/index.json
git commit -m "chore(registry): update latest buildable to ${{ steps.buildable.outputs.ref }}"
git push

View File

@@ -0,0 +1,38 @@
name: Update Module Index
on:
push:
branches:
- master
paths:
- "registry/modules/*.json"
- "registry/index.json"
- "scripts/update_module_index.py"
- "update-module-index.yml"
permissions:
contents: write
jobs:
update-registry-index:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Update module index
run: python3 scripts/update_module_index.py
- name: Commit updated index
run: |
if git diff --quiet registry/index.json; then
echo "No module index changes"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add registry/index.json
git commit -m "chore: update registry index"
git push

View File

@@ -1,7 +1,7 @@
<configuration>
<property name="PARTNER_HOME" value="${PARTNER_HOME:-${user.home}/.partner}"/>
<property name="PARTNER_LOG_DIR" value="${PARTNER_HOME}/state/trace/log"/>
<property name="LOG_LEVEL" value="${PARTNER_LOG_LEVEL}:-${partner.log.level:-INFO}"/>
<property name="LOG_LEVEL" value="${PARTNER_LOG_LEVEL:-${partner.log.level:-INFO}}"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>

View File

@@ -36,6 +36,7 @@ data class ModuleManifest(
/** Human-readable module description shown before installation. */
val description: String = "",
val version: String,
val source: Source,
val install: Install,
val config: Config? = null,

20
registry/index.json Normal file
View File

@@ -0,0 +1,20 @@
{
"partner": {
"latestBuildable": {
"url": "https://github.com/slhaf/Partner.git",
"ref": "buildable/0.5.0"
},
"latestRelease": {
"url": "https://github.com/slhaf/Partner/releases/download/rel-v0.5.0/partner-core-0.5.0.jar",
"version": "0.5.0"
}
},
"externalModules": [
{
"name": "OneBot Adapter",
"version": "0.5.0",
"withGateway": true,
"registryRef": "modules/onebot-adapter.json"
}
]
}

View File

View File

@@ -0,0 +1,58 @@
{
"id": "onebot_channel",
"name": "OneBot Adapter",
"version": "0.5.0",
"withGateway": true,
"description": "OneBot v11 reverse WebSocket gateway adapter for Partner. It accepts reverse WebSocket connections from a OneBot implementation and converts private message events into Partner input events.",
"source": {
"url": "https://github.com/slhaf/Partner.git",
"sourceDirName": "Partner",
"buildCommand": [
"mvn",
"-B",
"-DskipTests=true",
"-pl",
"Partner-External-Modules/Partner-Onebot-Adapter",
"-am",
"package"
],
"artifactDirectory": "Partner-External-Modules/Partner-Onebot-Adapter/target",
"artifactPattern": "partner-onebot-adapter-*.jar"
},
"install": {
"target": "resources/module/partner-onebot-adapter.jar"
},
"config": {
"target": "config/gateway.json",
"fields": [
{
"name": "port",
"label": "OneBot reverse WebSocket server port",
"type": "INT",
"default": "29700",
"required": true
},
{
"name": "hostname",
"label": "OneBot reverse WebSocket server hostname",
"type": "STRING",
"default": "127.0.0.1",
"required": true
},
{
"name": "path",
"label": "OneBot reverse WebSocket path",
"type": "STRING",
"default": "/onebot/v11/ws",
"required": true
},
{
"name": "token",
"label": "OneBot access token",
"type": "STRING",
"default": "",
"required": false
}
]
}
}

View File

@@ -0,0 +1,59 @@
#!/usr/bin/env python3
import json
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
INDEX_PATH = ROOT / "registry" / "index.json"
MODULES_DIR = ROOT / "registry" / "modules"
def load_json(path: Path) -> dict:
with path.open("r", encoding="utf-8") as f:
return json.load(f)
def write_json(path: Path, data: dict) -> None:
path.write_text(
json.dumps(data, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
def build_external_modules() -> list[dict]:
entries = []
if not MODULES_DIR.exists():
return entries
for manifest_path in sorted(MODULES_DIR.glob("*.json")):
manifest = load_json(manifest_path)
# 这里按你当前 ModuleManifest 的完整文件结构取字段。
# version 如果 manifest 里暂时没有,可以先默认取 "0.5.0" 或直接要求 manifest 必须有。
name = manifest["name"]
version = manifest["version"]
with_gateway = manifest.get("withGateway", False)
rel_path = manifest_path.relative_to(ROOT / "registry").as_posix()
entries.append(
{
"name": name,
"version": version,
"withGateway": with_gateway,
"registryRef": rel_path,
}
)
return entries
def main() -> None:
index = load_json(INDEX_PATH)
index["externalModules"] = build_external_modules()
write_json(INDEX_PATH, index)
if __name__ == "__main__":
main()