Skip to content

Commit 2346777

Browse files
committed
feat: configure crates.io publishing with feature flags and automated workflows
1 parent cdc3971 commit 2346777

File tree

3 files changed

+175
-3
lines changed

3 files changed

+175
-3
lines changed

.github/workflows/publish-test.yml

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Workflow: Test crates.io Publishing
2+
#
3+
# This workflow tests that the package can be prepared for crates.io publishing
4+
# without actually publishing it. Useful for validating the package before release.
5+
6+
name: Test Publishing
7+
8+
# Trigger conditions
9+
on:
10+
# Run on pushes to main to ensure package stays publishable
11+
push:
12+
branches: [ "main", "master" ]
13+
14+
# Run on pull requests to validate changes
15+
pull_request:
16+
branches: [ "main", "master" ]
17+
18+
# Allow manual triggering
19+
workflow_dispatch:
20+
21+
# Environment variables
22+
env:
23+
CARGO_TERM_COLOR: always
24+
RUST_BACKTRACE: 1
25+
26+
# Define jobs
27+
jobs:
28+
test-package:
29+
name: Test Package for Publishing
30+
runs-on: ubuntu-latest
31+
32+
steps:
33+
# Step 1: Check out the source code
34+
- name: Checkout source code
35+
uses: actions/checkout@v4
36+
37+
# Step 2: Install Rust toolchain
38+
- name: Install Rust toolchain
39+
uses: dtolnay/[email protected]
40+
41+
# Step 3: Setup Rust cache
42+
- name: Setup Rust cache
43+
uses: Swatinem/rust-cache@v2
44+
45+
# Step 4: Validate Cargo.toml metadata
46+
- name: Validate package metadata
47+
run: |
48+
echo "Validating Cargo.toml metadata for crates.io..."
49+
50+
# Check required fields are present
51+
cargo metadata --format-version 1 --no-deps | jq -r '.packages[0]' > package.json
52+
53+
# Verify required fields
54+
required_fields=("description" "license" "repository" "authors")
55+
for field in "${required_fields[@]}"; do
56+
value=$(jq -r ".$field" package.json)
57+
if [ "$value" == "null" ] || [ -z "$value" ]; then
58+
echo "❌ Missing required field: $field"
59+
exit 1
60+
else
61+
echo "✅ $field: $value"
62+
fi
63+
done
64+
65+
echo "✅ All required metadata fields are present"
66+
67+
# Step 5: Test packaging with examples-only feature (no git deps)
68+
- name: Test package with examples-only feature
69+
run: |
70+
echo "Testing package with examples-only feature (no git dependencies)..."
71+
cargo package --features examples-only --verbose
72+
echo "✅ Package builds successfully with examples-only feature"
73+
74+
# Step 6: Test packaging with default features (including MCP)
75+
- name: Test package with default features
76+
run: |
77+
echo "Testing package with default features..."
78+
# This may fail due to git dependency, which is expected
79+
if cargo package --verbose; then
80+
echo "✅ Package builds successfully with default features"
81+
else
82+
echo "⚠️ Package fails with default features (expected due to git dependency)"
83+
echo " This is normal - the examples-only feature should be used for crates.io"
84+
fi
85+
86+
# Step 7: Verify example binaries can build
87+
- name: Test example compilation
88+
run: |
89+
echo "Testing example binary compilation..."
90+
# Test a few key examples
91+
cargo build --features examples-only --bin example_01_hello_world
92+
cargo build --features examples-only --bin example_02_calculator
93+
cargo build --features examples-only --bin example_09_database
94+
echo "✅ Key examples compile successfully"
95+
96+
# Step 8: Generate package information
97+
- name: Generate package info
98+
run: |
99+
echo "# Package Information" > package-info.md
100+
echo "" >> package-info.md
101+
echo "**Name:** $(cargo metadata --format-version 1 --no-deps | jq -r '.packages[0].name')" >> package-info.md
102+
echo "**Version:** $(cargo metadata --format-version 1 --no-deps | jq -r '.packages[0].version')" >> package-info.md
103+
echo "**Description:** $(cargo metadata --format-version 1 --no-deps | jq -r '.packages[0].description')" >> package-info.md
104+
echo "" >> package-info.md
105+
echo "## Features" >> package-info.md
106+
echo "- \`default\`: Includes MCP SDK (git dependency)" >> package-info.md
107+
echo "- \`mcp\`: MCP SDK support" >> package-info.md
108+
echo "- \`examples-only\`: Just the educational code" >> package-info.md
109+
echo "" >> package-info.md
110+
echo "## Binaries" >> package-info.md
111+
cargo metadata --format-version 1 --no-deps | jq -r '.packages[0].targets[] | select(.kind[] == "bin") | "- " + .name' >> package-info.md
112+
113+
cat package-info.md
114+
115+
# Step 9: Upload package info
116+
- name: Upload package information
117+
uses: actions/upload-artifact@v4
118+
with:
119+
name: package-info
120+
path: package-info.md
121+
retention-days: 30

.github/workflows/release.yml

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,44 @@ jobs:
212212
asset_name: ${{ matrix.archive_name }}.${{ matrix.archive_extension }}
213213
asset_content_type: ${{ matrix.archive_extension == 'zip' && 'application/zip' || 'application/gzip' }}
214214

215-
# Job 3: Generate and upload checksums for verification
215+
# Job 3: Publish to crates.io
216+
publish-crate:
217+
name: Publish to crates.io
218+
needs: create-release
219+
runs-on: ubuntu-latest
220+
221+
steps:
222+
# Step 1: Check out the source code
223+
- name: Checkout source code
224+
uses: actions/checkout@v4
225+
226+
# Step 2: Install Rust toolchain
227+
- name: Install Rust toolchain
228+
uses: dtolnay/[email protected]
229+
230+
# Step 3: Setup Rust cache
231+
- name: Setup Rust cache
232+
uses: Swatinem/rust-cache@v2
233+
234+
# Step 4: Verify the package can be published
235+
- name: Verify package
236+
run: |
237+
echo "Verifying package for crates.io publishing..."
238+
cargo package --verbose
239+
cargo package --list
240+
241+
# Step 5: Publish to crates.io
242+
- name: Publish to crates.io
243+
run: |
244+
echo "Publishing MCP Rust Examples to crates.io..."
245+
cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }} --verbose
246+
env:
247+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
248+
249+
# Job 4: Generate and upload checksums for verification
216250
checksums:
217251
name: Generate Checksums
218-
needs: [create-release, build]
252+
needs: [create-release, build, publish-crate]
219253
runs-on: ubuntu-latest
220254

221255
steps:

Cargo.toml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
name = "mcp_rust_examples"
33
version = "0.1.0"
44
edition = "2021"
5+
authors = ["Hamze Ghalebi <[email protected]>"]
6+
license = "MIT"
7+
description = "Complete educational resource for learning MCP (Model Context Protocol) development with Rust - 20 comprehensive examples from beginner to enterprise level"
8+
repository = "https://github.com/RustSandbox/MCP-Development-with-Rust"
9+
documentation = "https://rustsandbox.github.io/MCP-Development-with-Rust/"
10+
homepage = "https://rustsandbox.github.io/MCP-Development-with-Rust/"
11+
readme = "README.md"
12+
keywords = ["mcp", "protocol", "examples", "tutorial", "education"]
13+
categories = ["development-tools", "tutorial", "network-programming"]
14+
exclude = [".github/", "scripts/", "test-deployment.md", ".actrc", ".gitignore"]
515

616
[[bin]]
717
name = "example_01_hello_world"
@@ -85,10 +95,11 @@ path = "src/examples/example_20_enterprise_server.rs"
8595

8696
[dependencies]
8797
# Core MCP SDK - using development branch for latest features
98+
# Note: Made optional for crates.io publishing compatibility
8899
rmcp = { git = "https://github.com/modelcontextprotocol/rust-sdk", branch = "main", features = [
89100
"server",
90101
"client",
91-
] }
102+
], optional = true }
92103

93104
# Essential async runtime
94105
tokio = { version = "1.0", features = ["full"] }
@@ -126,3 +137,9 @@ sha2 = "0.10"
126137

127138
[dev-dependencies]
128139
tempfile = "3.0"
140+
141+
[features]
142+
default = ["mcp"]
143+
mcp = ["rmcp"]
144+
examples-only = [
145+
] # For users who just want the educational code without MCP dependencies

0 commit comments

Comments
 (0)