Skip to content

Commit bf870a0

Browse files
committed
✨ 添加自动发布系统,支持多平台构建和版本一致性检查
✨ 更新发布指南文档,详细说明发布流程和脚本用法
1 parent 9cf3ad9 commit bf870a0

File tree

7 files changed

+795
-2
lines changed

7 files changed

+795
-2
lines changed

.cunzhi-memory/context.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
- CodeNexus项目已完成!实现了完整的多项目支持架构,包含13个MCP工具接口、路径安全验证、项目隔离存储、智能查询引擎等核心功能。项目可生产使用,所有测试通过,代码质量高,文档完善。解决了MCP服务器启动目录不可控的关键问题。
44
- 已为CodeNexus项目建立完整代码关系体系:17个文件100%标记和注释,31个依赖关系,37个多维度标签,支持智能查询、关系分析、架构导航等功能
55
- 已为CodeNexus查询引擎实现完整操作符支持:NOT、OR、通配符、复合查询,支持复杂表达式如"(type:manager OR type:adapter) AND NOT module:core",并更新README文档说明新功能
6+
- 为CodeNexus项目创建了完整的自动发布系统,参考cunzhi项目的GitHub Actions配置。包含:1) .github/workflows/release.yml - 多平台构建和自动发布工作流;2) cliff.toml - git-cliff配置文件用于生成changelog;3) scripts/release.ps1和release.sh - Windows和Linux/macOS发布脚本;4) docs/RELEASE_GUIDE.md - 详细的发布指南文档。系统支持版本一致性检查、自动changelog生成、多平台二进制构建、GitHub Release创建等功能。

.cunzhi-memory/metadata.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"project_path": "\\\\?\\E:\\Projects\\MyProjects\\code_nexus",
3-
"last_organized": "2025-07-08T08:12:04.705590400Z",
4-
"total_entries": 5,
3+
"last_organized": "2025-07-08T08:47:34.946942400Z",
4+
"total_entries": 6,
55
"version": "1.0.0"
66
}

.github/workflows/release.yml

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
tags: ['v*']
6+
workflow_dispatch:
7+
8+
jobs:
9+
build:
10+
permissions:
11+
contents: write
12+
strategy:
13+
fail-fast: false
14+
matrix:
15+
include:
16+
- platform: macos-latest
17+
target: aarch64-apple-darwin
18+
name: macos-aarch64
19+
- platform: macos-latest
20+
target: x86_64-apple-darwin
21+
name: macos-x86_64
22+
- platform: ubuntu-22.04
23+
target: x86_64-unknown-linux-gnu
24+
name: linux-x86_64
25+
- platform: windows-latest
26+
target: x86_64-pc-windows-msvc
27+
name: windows-x86_64
28+
29+
runs-on: ${{ matrix.platform }}
30+
31+
steps:
32+
- uses: actions/checkout@v4
33+
34+
- name: Install Rust stable
35+
uses: dtolnay/rust-toolchain@stable
36+
with:
37+
targets: ${{ matrix.target }}
38+
39+
- name: Rust cache
40+
uses: swatinem/rust-cache@v2
41+
with:
42+
key: ${{ matrix.target }}
43+
44+
- name: Build release binary
45+
run: cargo build --release --target ${{ matrix.target }}
46+
47+
- name: Create release package
48+
shell: bash
49+
run: |
50+
mkdir -p release-package
51+
52+
# 获取完整的 tag 名称
53+
TAG_NAME="${{ github.ref_name }}"
54+
55+
# 确定二进制文件名和扩展名
56+
if [[ "${{ matrix.platform }}" == "windows-latest" ]]; then
57+
BINARY_NAME="code-nexus.exe"
58+
ARCHIVE_EXT="zip"
59+
else
60+
BINARY_NAME="code-nexus"
61+
ARCHIVE_EXT="tar.gz"
62+
fi
63+
64+
# 复制二进制文件
65+
cp "target/${{ matrix.target }}/release/$BINARY_NAME" release-package/
66+
67+
# 复制其他文件
68+
cp README.md release-package/ || true
69+
cp LICENSE release-package/ || true
70+
71+
# 创建压缩包
72+
cd release-package
73+
if [[ "${{ matrix.platform }}" == "windows-latest" ]]; then
74+
7z a "../code-nexus-${TAG_NAME}-${{ matrix.name }}.zip" *
75+
else
76+
tar -czf "../code-nexus-${TAG_NAME}-${{ matrix.name }}.tar.gz" *
77+
fi
78+
79+
- name: Upload artifacts
80+
uses: actions/upload-artifact@v4
81+
with:
82+
name: code-nexus-${{ matrix.name }}
83+
path: |
84+
code-nexus-*.tar.gz
85+
code-nexus-*.zip
86+
if-no-files-found: ignore
87+
88+
release:
89+
name: Create Release
90+
needs: build
91+
runs-on: ubuntu-latest
92+
if: startsWith(github.ref, 'refs/tags/v')
93+
94+
steps:
95+
- name: Checkout code
96+
uses: actions/checkout@v4
97+
with:
98+
fetch-depth: 0
99+
100+
- name: Verify version consistency
101+
run: |
102+
# 获取 git tag 版本号(去掉 v 前缀)
103+
TAG_NAME="${{ github.ref_name }}"
104+
TAG_VERSION_NUMBER=${TAG_NAME#v}
105+
106+
# 从 Cargo.toml 读取版本号
107+
PROJECT_VERSION=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)
108+
109+
echo "Git tag version: ${TAG_VERSION_NUMBER}"
110+
echo "Cargo.toml version: ${PROJECT_VERSION}"
111+
112+
# 检查版本是否一致
113+
if [ "${TAG_VERSION_NUMBER}" != "${PROJECT_VERSION}" ]; then
114+
echo "❌ Version mismatch detected!"
115+
echo "Git tag version: ${TAG_VERSION_NUMBER}"
116+
echo "Cargo.toml version: ${PROJECT_VERSION}"
117+
echo ""
118+
echo "Please ensure the git tag matches the version in Cargo.toml."
119+
echo "You can either:"
120+
echo "1. Update Cargo.toml to match tag: ${TAG_VERSION_NUMBER}"
121+
echo "2. Create a new tag that matches Cargo.toml version: v${PROJECT_VERSION}"
122+
exit 1
123+
fi
124+
125+
echo "✅ Version consistency check passed: ${TAG_VERSION_NUMBER}"
126+
127+
- name: Download all artifacts
128+
uses: actions/download-artifact@v4
129+
with:
130+
path: artifacts
131+
132+
- name: Install git-cliff
133+
uses: taiki-e/install-action@git-cliff
134+
135+
- name: Generate changelog and release title
136+
id: changelog
137+
run: |
138+
# 从 GitHub API 获取最新的 release 版本
139+
echo "Fetching latest release from GitHub API..."
140+
LATEST_RELEASE=$(curl -s "https://api.github.com/repos/${{ github.repository }}/releases/latest" | jq -r '.tag_name // empty' 2>/dev/null || echo "")
141+
142+
if [ -z "$LATEST_RELEASE" ] || [ "$LATEST_RELEASE" = "null" ]; then
143+
echo "GitHub API failed or no previous release found, falling back to git tags"
144+
# 回退到使用 git tag 获取上一个版本
145+
PREVIOUS_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -2 | tail -1)
146+
if [ -z "$PREVIOUS_TAG" ]; then
147+
echo "No previous tags found, generating full changelog"
148+
else
149+
echo "Found previous tag: $PREVIOUS_TAG"
150+
fi
151+
else
152+
PREVIOUS_TAG="$LATEST_RELEASE"
153+
echo "Found previous release: $PREVIOUS_TAG"
154+
fi
155+
156+
echo "Current tag: ${{ github.ref_name }}"
157+
echo "Previous version: $PREVIOUS_TAG"
158+
159+
if [ -z "$PREVIOUS_TAG" ]; then
160+
# 如果没有上一个版本,生成所有提交的 changelog
161+
git-cliff --tag ${{ github.ref_name }} --output changelog.md
162+
else
163+
# 只生成从上一个版本到当前版本的 changelog
164+
git-cliff $PREVIOUS_TAG..${{ github.ref_name }} --output changelog.md
165+
# 添加 Full Changelog 链接
166+
echo "" >> changelog.md
167+
echo "**Full Changelog**: [$PREVIOUS_TAG...${{ github.ref_name }}](https://github.com/${{ github.repository }}/compare/$PREVIOUS_TAG...${{ github.ref_name }})" >> changelog.md
168+
fi
169+
170+
# 生成发布标题
171+
VERSION_NUMBER="${{ github.ref_name }}"
172+
VERSION_NUMBER=${VERSION_NUMBER#v} # 移除 v 前缀
173+
174+
# 从最近的提交中提取主要功能作为标题
175+
if [ -z "$PREVIOUS_TAG" ]; then
176+
COMMIT_RANGE="${{ github.ref_name }}"
177+
else
178+
COMMIT_RANGE="$PREVIOUS_TAG..${{ github.ref_name }}"
179+
fi
180+
181+
MAIN_FEATURE=$(git log --oneline $COMMIT_RANGE | grep -E "^[a-f0-9]+ (feat|fix)" | head -1 | sed 's/^[a-f0-9]* //' | sed 's/^feat: /✨ /' | sed 's/^fix: /🐞 /')
182+
183+
if [ -z "$MAIN_FEATURE" ]; then
184+
RELEASE_TITLE="$VERSION_NUMBER 📦 版本更新"
185+
else
186+
RELEASE_TITLE="$VERSION_NUMBER $MAIN_FEATURE"
187+
fi
188+
189+
echo "release_title=$RELEASE_TITLE" >> $GITHUB_OUTPUT
190+
echo "Generated release title: $RELEASE_TITLE"
191+
192+
- name: Create Release
193+
uses: softprops/action-gh-release@v1
194+
with:
195+
files: |
196+
artifacts/*/code-nexus-*.tar.gz
197+
artifacts/*/code-nexus-*.zip
198+
draft: false
199+
prerelease: false
200+
generate_release_notes: false
201+
name: ${{ steps.changelog.outputs.release_title }}
202+
body_path: changelog.md
203+
env:
204+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

cliff.toml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# git-cliff 配置文件
2+
# 用于生成 CHANGELOG.md
3+
4+
[changelog]
5+
# changelog header
6+
header = """
7+
# Changelog
8+
9+
All notable changes to this project will be documented in this file.
10+
11+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
12+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
13+
14+
"""
15+
# template for the changelog body
16+
# https://keats.github.io/tera/docs/#introduction
17+
body = """
18+
{% if version -%}
19+
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
20+
{% else -%}
21+
## [unreleased]
22+
{% endif -%}
23+
{% for group, commits in commits | group_by(attribute="group") %}
24+
### {{ group | striptags | trim | upper_first }}
25+
{% for commit in commits %}
26+
- {% if commit.scope %}**{{commit.scope}}**: {% endif %}{{ commit.message | upper_first }}\
27+
{% endfor %}
28+
{% endfor %}\n
29+
"""
30+
# remove the leading and trailing whitespace from the template
31+
trim = true
32+
# changelog footer
33+
footer = """
34+
<!-- generated by git-cliff -->
35+
"""
36+
37+
[git]
38+
# parse the commits based on https://www.conventionalcommits.org
39+
conventional_commits = true
40+
# filter out the commits that are not conventional
41+
filter_unconventional = true
42+
# process each line of a commit as an individual commit
43+
split_commits = false
44+
# regex for preprocessing the commit messages
45+
commit_preprocessors = [
46+
# Replace issue numbers
47+
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/your-username/code-nexus/issues/${2}))"},
48+
# Check spelling of the commit with https://github.com/crate-ci/typos
49+
# If the spelling is incorrect, it will be automatically fixed.
50+
#{ pattern = '.*', replace_command = 'typos --write-changes -' },
51+
]
52+
# regex for parsing and grouping commits
53+
commit_parsers = [
54+
{ message = "^feat", group = "<!-- 0 -->🚀 Features"},
55+
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes"},
56+
{ message = "^doc", group = "<!-- 3 -->📚 Documentation"},
57+
{ message = "^perf", group = "<!-- 4 -->⚡ Performance"},
58+
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor"},
59+
{ message = "^style", group = "<!-- 5 -->🎨 Styling"},
60+
{ message = "^test", group = "<!-- 6 -->🧪 Testing"},
61+
{ message = "^chore\\(release\\): prepare for", skip = true},
62+
{ message = "^chore\\(deps.*\\)", skip = true},
63+
{ message = "^chore\\(pr\\)", skip = true},
64+
{ message = "^chore\\(pull\\)", skip = true},
65+
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks"},
66+
{ body = ".*security", group = "<!-- 8 -->🛡️ Security"},
67+
{ message = "^revert", group = "<!-- 9 -->◀️ Revert"},
68+
]
69+
# protect breaking changes from being skipped due to matching a skipping commit_parser
70+
protect_breaking_commits = false
71+
# filter out the commits that are not matched by commit parsers
72+
filter_commits = false
73+
# regex for matching git tags
74+
tag_pattern = "v[0-9].*"
75+
76+
# regex for skipping tags
77+
skip_tags = "v0.1.0-beta.1"
78+
# regex for ignoring tags
79+
ignore_tags = ""
80+
# sort the tags topologically
81+
topo_order = false
82+
# sort the commits inside sections by oldest/newest order
83+
sort_commits = "oldest"
84+
# limit the number of commits included in the changelog.
85+
# limit_commits = 42

0 commit comments

Comments
 (0)