Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 19 additions & 67 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
name: CI

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

env:
CARGO_TERM_COLOR: always
RUSTFLAGS: -Dwarnings

jobs:
check:
name: Check Examples
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt

- name: Cache cargo registry
uses: actions/cache@v4
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
with:
path: |
~/.cargo/registry
Expand All @@ -32,39 +31,21 @@ jobs:
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }}
restore-keys: |
${{ runner.os }}-cargo-

- name: Check all examples compile
run: |
echo "🔍 Checking all examples..."

EXAMPLES=(
"hello-world"
"crud-api"
"auth-api"
"cors-test"
"sqlx-crud"
"event-sourcing"
"graphql-api"
"mcp-server"
"microservices"
"microservices-advanced"
"middleware-chain"
"phase11-demo"
"rate-limit-demo"
"templates"
"toon-api"
"websocket"
"proof-of-concept"
"01-hello-world"
"02-crud-api"
"03-jwt-auth"
"04-sse-stream"
)

FAILED=()

for example in "${EXAMPLES[@]}"; do
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📦 Checking: $example"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

if cd "$example" && cargo check --quiet 2>&1; then
echo "✅ $example: OK"
else
Expand All @@ -73,12 +54,10 @@ jobs:
fi
cd ..
done

echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "📊 Summary"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

if [ ${#FAILED[@]} -eq 0 ]; then
echo "✅ All ${#EXAMPLES[@]} examples passed!"
exit 0
Expand All @@ -89,70 +68,46 @@ jobs:
done
exit 1
fi

# Serverless Lambda uses different runtime, check separately
- name: Check serverless-lambda
run: |
echo "📦 Checking: serverless-lambda (AWS Lambda runtime)"
cd serverless-lambda && cargo check --quiet
echo "✅ serverless-lambda: OK"

fmt:
name: Format Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt

- name: Check formatting
run: |
echo "🎨 Checking code formatting..."

EXAMPLES=(
"hello-world"
"crud-api"
"auth-api"
"cors-test"
"sqlx-crud"
"event-sourcing"
"graphql-api"
"mcp-server"
"microservices"
"microservices-advanced"
"middleware-chain"
"phase11-demo"
"rate-limit-demo"
"serverless-lambda"
"templates"
"toon-api"
"websocket"
"proof-of-concept"
"01-hello-world"
"02-crud-api"
"03-jwt-auth"
"04-sse-stream"
)

for example in "${EXAMPLES[@]}"; do
echo "Checking format: $example"
cd "$example" && cargo fmt -- --check && cd ..
done

echo "✅ All formatting checks passed!"

clippy:
name: Clippy Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: clippy

- name: Cache cargo registry
uses: actions/cache@v4
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
with:
path: |
~/.cargo/registry
Expand All @@ -161,15 +116,12 @@ jobs:
key: ${{ runner.os }}-cargo-clippy-${{ hashFiles('**/Cargo.toml') }}
restore-keys: |
${{ runner.os }}-cargo-clippy-

- name: Run Clippy on examples
run: |
echo "🔎 Running Clippy lints..."

# Quick clippy check on a few key examples
for example in hello-world crud-api auth-api middleware-chain; do
for example in 01-hello-world 02-crud-api 03-jwt-auth 04-sse-stream ; do
echo "Linting: $example"
cd "$example" && cargo clippy --quiet -- -D warnings && cd ..
done

echo "✅ Clippy checks passed!"
9 changes: 6 additions & 3 deletions 02-crud-api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct UpdateNote {
// Handler return types must use ApiError directly (it implements ResponseModifier).
// NoteError is kept here to show the derive pattern; use ApiError in handlers.
#[derive(ApiError)]
#[allow(dead_code)]
enum NoteError {
#[error(status = 404, code = "NOT_FOUND", message = "Note not found")]
NotFound,
Expand All @@ -80,9 +81,9 @@ impl From<NoteError> for ApiError {
#[summary("List all notes")]
async fn list_notes(State(state): State<AppState>) -> Json<Vec<Note>> {
let notes = state.notes.read().await;
let mut items: Vec<_> = notes.values().cloned().collect();
let mut items: Vec<_> = notes.values().collect();
items.sort_by_key(|n| n.id);
Json(items)
Json(items.into_iter().cloned().collect())
}

#[post("/notes")]
Expand Down Expand Up @@ -130,7 +131,9 @@ async fn update_note(
Json(payload): Json<UpdateNote>,
) -> Result<Json<Note>, ApiError> {
let mut notes = state.notes.write().await;
let note = notes.get_mut(&id).ok_or_else(|| ApiError::not_found("Note not found"))?;
let note = notes
.get_mut(&id)
.ok_or_else(|| ApiError::not_found("Note not found"))?;
if let Some(t) = payload.title {
note.title = t;
}
Expand Down
3 changes: 2 additions & 1 deletion 03-jwt-auth/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct ProfileResponse {
// NOTE: #[derive(ApiError)] generates IntoResponse for custom error enums.
// Handler return types must use ApiError directly (it implements ResponseModifier).
#[derive(ApiError)]
#[allow(dead_code)]
enum AuthError {
#[error(status = 401, code = "UNAUTHORIZED", message = "Invalid credentials")]
InvalidCredentials,
Expand Down Expand Up @@ -101,7 +102,7 @@ async fn login(Json(payload): Json<LoginRequest>) -> Result<Json<TokenResponse>,
exp: now_plus_secs(ttl),
};

let token = create_token(&claims, JWT_SECRET).map_err(|_| ApiError::unauthorized("Invalid credentials"))?;;
let token = create_token(&claims, JWT_SECRET).map_err(|_| ApiError::unauthorized("Invalid credentials"))?;
Ok(Json(TokenResponse {
token,
expires_in: ttl,
Expand Down
Loading