name: Release on: push: branches: [main] jobs: release: runs-on: ubuntu-builder steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # ── 自动标签:从合并进来的 PR body 提取 v*.*.* ── - name: Auto-tag from merged PR id: autotag run: | set -e # 已有标签 → 跳过 EXISTING=$(git tag --points-at HEAD | grep '^v' | head -n1) if [ -n "$EXISTING" ]; then echo "Tag $EXISTING already exists" echo "tag=$EXISTING" >> "$GITHUB_OUTPUT" exit 0 fi # 非 merge commit → 跳过(直接 push 不处理) PARENTS=$(git log --format="%P" -1 | wc -w) if [ "$PARENTS" -lt 2 ]; then echo "Not a merge commit, skip auto-tag" exit 0 fi # 从 merge commit message 提取 PR 号 COMMIT_MSG=$(git log --format="%B" -1) PR_NUM=$(echo "$COMMIT_MSG" | grep -oP '#\K\d+' | head -1) if [ -z "$PR_NUM" ]; then echo "No PR number found in merge message" exit 0 fi echo "Merge commit for PR #$PR_NUM" # 通过 Gitea API 获取 PR body,提取版本号 API="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/pulls/${PR_NUM}" TOKEN="${{ gitea.token }}" PR_BODY=$(curl -s -H "Authorization: token ${TOKEN}" "${API}" | \ python3 -c "import sys,json,re;pr=json.load(sys.stdin);body=pr.get('body','') or '';m=re.search(r'v\d+\.\d+\.\d+',body);print(m.group() if m else '')") if [ -z "$PR_BODY" ]; then echo "No version pattern v*.*.* found in PR body" exit 0 fi VERSION="$PR_BODY" echo "Found version: $VERSION" # 创建本地标签 git config user.email "ci@datarouter" git config user.name "DataRouter CI" git tag -a "$VERSION" -m "Release $VERSION" echo "Created local tag: $VERSION" # 推送到远端(不会触发本 workflow — 仅匹配 branches: [main]) ORIGIN=$(git config --get remote.origin.url) PUSH_URL="https://oauth2:${TOKEN}@${ORIGIN#https://}" git push "$PUSH_URL" "$VERSION" echo "Pushed tag: $VERSION" echo "tag=$VERSION" >> "$GITHUB_OUTPUT" # ── 读取标签(已有标签 / auto-tag 创建的标签)── - name: Read tag from HEAD id: tag run: | TAG=$(git tag --points-at HEAD | grep '^v' | head -n1) [ -n "$TAG" ] || { echo "No version tag on HEAD"; exit 78; } echo "tag=$TAG" >> "$GITHUB_OUTPUT" - name: Install cross-compilers run: | sudo apt-get update sudo apt-get install -y \ gcc-arm-linux-gnueabihf \ gcc-aarch64-linux-gnu \ gcc-mingw-w64-x86-64 \ gcc-arm-none-eabi - name: Build all targets run: | for entry in \ "linux-amd64|ON|" \ "linux-arm64|OFF|-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-linux-arm64.cmake" \ "linux-armhf|OFF|-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-linux-armhf.cmake" \ "windows-amd64|OFF|-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-windows-amd64.cmake -DBUILD_EXAMPLES=OFF" \ "baremetal-arm32|OFF|-DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-baremetal-arm32.cmake -DBUILD_EXAMPLES=OFF -DBUILD_SHARED=OFF" do IFS='|' read -r name testing extra <<< "$entry" echo ">>> Building $name" cmake -S . -B "build-$name" -DBUILD_TESTING=$testing $extra cmake --build "build-$name" [ "$testing" = "ON" ] && ctest --test-dir "build-$name" --output-on-failure pkg="datarouter-$name" cmake --install "build-$name" --prefix "dist/$pkg" done - name: Cortex-M compile matrix run: | cmake -S . -B build-cortex-m -DDR_COMPILE_CHECK=ON cmake --build build-cortex-m --parallel $(nproc) echo "--- Cortex-M build matrix: all variants passed ---" - name: Create release & upload assets run: | TAG="${{ steps.tag.outputs.tag }}" API="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/releases" TOKEN="${{ gitea.token }}" # Check if release already exists echo "=== Checking existing releases for $TAG ===" EXISTING=$(curl -s -H "Authorization: token ${TOKEN}" "${API}" | \ python3 -c "import sys,json;rels=json.load(sys.stdin);print(next((r['id'] for r in rels if r['tag_name']=='${TAG}'),''))") if [ -n "$EXISTING" ]; then ID="$EXISTING" echo "Release already exists (ID=$ID), updating it" else echo "=== Creating release $TAG ===" RESP=$(curl -s -X POST \ -H "Authorization: token ${TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"tag_name\":\"${TAG}\",\"name\":\"DataRouter ${TAG}\"}" \ "$API") ID=$(echo "$RESP" | python3 -c "import sys,json;d=json.loads(sys.stdin.read());print(d['id'])") fi for dir in dist/*/; do name="$(basename "$dir").tar.gz" tar czf "/tmp/$name" -C "$dir" . echo "Uploading $name" curl -s -X POST \ -H "Authorization: token ${TOKEN}" \ -H "Content-Type: application/octet-stream" \ --data-binary @"/tmp/$name" \ "${API}/${ID}/assets?name=${name}" done