Add comprehensive release infrastructure and tooling

- Add automated GitHub Actions workflow for multi-platform releases
- Add release script with version management and validation
- Add Docker container support with multi-stage builds
- Add comprehensive release documentation and templates
- Update Cargo.toml with complete package metadata
- Add command-line argument parsing with security options
- Update README with detailed configuration examples

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Andy
2025-08-11 14:40:53 +08:00
parent 39e94c1b13
commit 705e8bfa91
11 changed files with 1819 additions and 30 deletions
+355
View File
@@ -0,0 +1,355 @@
#!/bin/bash
# Release script for docx-mcp
# This script helps with version management and release preparation
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions
info() {
echo -e "${BLUE}$1${NC}"
}
success() {
echo -e "${GREEN}$1${NC}"
}
warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
error() {
echo -e "${RED}$1${NC}"
}
# Check if we're in a git repository
check_git_repo() {
if ! git rev-parse --git-dir > /dev/null 2>&1; then
error "Not in a git repository"
exit 1
fi
}
# Check if working directory is clean
check_clean_working_dir() {
if ! git diff-index --quiet HEAD --; then
error "Working directory is not clean. Please commit or stash your changes."
exit 1
fi
}
# Get current version from Cargo.toml
get_current_version() {
grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/'
}
# Update version in Cargo.toml
update_version() {
local new_version=$1
info "Updating version to $new_version"
# Update Cargo.toml
sed -i.bak "s/^version = \".*\"/version = \"$new_version\"/" Cargo.toml
rm Cargo.toml.bak
# Update Cargo.lock
cargo update -p docx-mcp
success "Version updated to $new_version"
}
# Generate changelog since last tag
generate_changelog() {
local last_tag=$(git tag --sort=-version:refname | head -1)
local new_version=$1
info "Generating changelog since $last_tag"
if [ -n "$last_tag" ]; then
git log --pretty=format:"- %s (%h)" --no-merges ${last_tag}..HEAD > CHANGELOG.tmp
else
git log --pretty=format:"- %s (%h)" --no-merges > CHANGELOG.tmp
fi
echo "## Release $new_version ($(date +%Y-%m-%d))"
echo ""
cat CHANGELOG.tmp
echo ""
rm CHANGELOG.tmp
}
# Run pre-release checks
run_checks() {
info "Running pre-release checks..."
# Format check
info "Checking code formatting..."
cargo fmt --all -- --check
success "Code formatting is correct"
# Clippy check
info "Running Clippy..."
cargo clippy --all-targets --all-features -- -D warnings
success "Clippy checks passed"
# Tests
info "Running tests..."
cargo test --all-features
success "All tests passed"
# Build check
info "Testing release build..."
cargo build --release --all-features
success "Release build successful"
# Package check
info "Testing package..."
cargo package --dry-run
success "Package validation passed"
}
# Create and push git tag
create_tag() {
local version=$1
local tag="v$version"
info "Creating git tag $tag"
# Create annotated tag
git tag -a "$tag" -m "Release $tag"
success "Created tag $tag"
# Ask if user wants to push
echo -n "Push tag to origin? [y/N]: "
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
git push origin "$tag"
success "Tag pushed to origin"
else
warning "Tag not pushed. Remember to push it manually: git push origin $tag"
fi
}
# Show usage information
usage() {
cat << EOF
Usage: $0 [COMMAND] [OPTIONS]
Commands:
patch Bump patch version (0.1.0 -> 0.1.1)
minor Bump minor version (0.1.0 -> 0.2.0)
major Bump major version (0.1.0 -> 1.0.0)
version X.Y.Z Set specific version
check Run pre-release checks only
changelog Generate changelog since last tag
tag Create git tag for current version
Options:
--dry-run Show what would be done without making changes
--no-checks Skip pre-release checks (not recommended)
--no-tag Don't create git tag
--help Show this help message
Examples:
$0 patch # Bump to next patch version
$0 version 1.0.0 # Set version to 1.0.0
$0 check # Run all pre-release checks
$0 patch --dry-run # Show what patch release would do
EOF
}
# Parse version bump type
bump_version() {
local current_version=$1
local bump_type=$2
# Split version into components
IFS='.' read -ra VERSION_PARTS <<< "$current_version"
local major=${VERSION_PARTS[0]}
local minor=${VERSION_PARTS[1]}
local patch=${VERSION_PARTS[2]}
case $bump_type in
"patch")
patch=$((patch + 1))
;;
"minor")
minor=$((minor + 1))
patch=0
;;
"major")
major=$((major + 1))
minor=0
patch=0
;;
*)
error "Invalid bump type: $bump_type"
exit 1
;;
esac
echo "${major}.${minor}.${patch}"
}
# Validate version format
validate_version() {
local version=$1
if ! [[ $version =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$ ]]; then
error "Invalid version format: $version"
error "Expected format: X.Y.Z or X.Y.Z-suffix"
exit 1
fi
}
# Main script logic
main() {
local command=$1
local dry_run=false
local no_checks=false
local no_tag=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run)
dry_run=true
shift
;;
--no-checks)
no_checks=true
shift
;;
--no-tag)
no_tag=true
shift
;;
--help)
usage
exit 0
;;
*)
if [ -z "$command" ]; then
command=$1
elif [ -z "$version_arg" ] && [ "$command" = "version" ]; then
version_arg=$1
fi
shift
;;
esac
done
# Check if command provided
if [ -z "$command" ]; then
usage
exit 1
fi
# Basic checks
check_git_repo
if [ "$dry_run" = false ]; then
check_clean_working_dir
fi
current_version=$(get_current_version)
info "Current version: $current_version"
case $command in
"patch"|"minor"|"major")
new_version=$(bump_version "$current_version" "$command")
;;
"version")
if [ -z "$version_arg" ]; then
error "Version argument required for 'version' command"
exit 1
fi
new_version=$version_arg
validate_version "$new_version"
;;
"check")
run_checks
success "All pre-release checks passed!"
exit 0
;;
"changelog")
generate_changelog "$current_version"
exit 0
;;
"tag")
if [ "$dry_run" = true ]; then
info "Would create tag v$current_version"
else
create_tag "$current_version"
fi
exit 0
;;
*)
error "Unknown command: $command"
usage
exit 1
;;
esac
info "New version will be: $new_version"
if [ "$dry_run" = true ]; then
warning "DRY RUN MODE - No changes will be made"
info "Would update version from $current_version to $new_version"
if [ "$no_checks" = false ]; then
info "Would run pre-release checks"
fi
if [ "$no_tag" = false ]; then
info "Would create git tag v$new_version"
fi
exit 0
fi
# Confirm with user
echo -n "Proceed with release $new_version? [y/N]: "
read -r response
if [[ ! "$response" =~ ^[Yy]$ ]]; then
warning "Release cancelled"
exit 0
fi
# Run pre-release checks
if [ "$no_checks" = false ]; then
run_checks
fi
# Update version
update_version "$new_version"
# Commit version bump
git add Cargo.toml Cargo.lock
git commit -m "Release $new_version"
success "Version bump committed"
# Create tag
if [ "$no_tag" = false ]; then
create_tag "$new_version"
fi
# Generate changelog for reference
info "Changelog for release:"
generate_changelog "$new_version"
success "Release $new_version completed!"
info "Next steps:"
info "1. Push commits: git push origin main"
if [ "$no_tag" = false ]; then
info "2. Push tag: git push origin v$new_version (if not done already)"
fi
info "3. GitHub Actions will automatically create the release"
}
# Run main function with all arguments
main "$@"