Skip to content

Commit

Permalink
Add new GitHub Actions job to check that examples compile and are pro…
Browse files Browse the repository at this point in the history
…perly formatted (#870)

* Add workflow job to test examples on push or PR (`fmt` + `clippy`)

* Fix clippy and formatting warnings and errors when running the new example validation script

* Change caching key of the example validation job

* Fix typo in `todo-actix` example

* Fix missing execute permission on `validate-examples.sh` file

* Modify job caching path to manually include `target`s from examples

* Manually install stable and nightly Rust on `test (examples)` job

This also installs the `clippy` and `rustfmt` components.
  • Loading branch information
simongoricar authored Feb 19, 2024
1 parent 7b74942 commit 8ab1e96
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 16 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,36 @@ jobs:
if [[ ${{ steps.changes.outputs.changes }} == true ]]; then
./scripts/test.sh ${{ matrix.crate }}
fi
test-examples-compile:
name: "test (examples)"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2

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

- name: Install nightly Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly
components: clippy, rustfmt

- uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
examples/**/target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}_examples

- name: Test that examples compile
run: |
./scripts/validate-examples.sh
2 changes: 1 addition & 1 deletion examples/raw-json-actix/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{error::Error, net::Ipv4Addr};

use actix_web::{
middleware::Logger, patch, App, HttpResponse, HttpServer, Responder, Result, web::Json,
middleware::Logger, patch, web::Json, App, HttpResponse, HttpServer, Responder, Result,
};
use serde_json::Value;
use utoipa::OpenApi;
Expand Down
4 changes: 2 additions & 2 deletions examples/rocket-todo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ mod todo {

async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
match request.headers().get("todo_apikey").next() {
Some(key) if key == "utoipa-rocks" => Outcome::Success(RequireApiKey),
Some("utoipa-rocks") => Outcome::Success(RequireApiKey),
None => Outcome::Error((
Status::Unauthorized,
TodoError::Unauthorized(String::from("missing api key")),
Expand All @@ -144,7 +144,7 @@ mod todo {

async fn from_request(request: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
match request.headers().get("todo_apikey").next() {
Some(key) if key == "utoipa-rocks" => {
Some("utoipa-rocks") => {
log::info!("authenticated");
Outcome::Success(LogApiKey)
}
Expand Down
18 changes: 9 additions & 9 deletions examples/simple-axum/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use axum::{routing::get, Json};
use utoipa::OpenApi;

#[derive(OpenApi)]
#[openapi(
paths(openapi),
)]
#[openapi(paths(openapi))]
struct ApiDoc;

/// Return JSON version of an OpenAPI schema
Expand All @@ -23,10 +21,12 @@ async fn openapi() -> Json<utoipa::openapi::OpenApi> {

#[tokio::main]
async fn main() {
let sa : SocketAddr = "127.0.0.1:8080".parse().unwrap();
let l = tokio::net::TcpListener::bind(sa).await.unwrap();
let app = axum::Router::new()
.route("/api-docs/openapi.json", get(openapi))
;
axum::serve(l, app.into_make_service()).await.unwrap()
let socket_address: SocketAddr = "127.0.0.1:8080".parse().unwrap();
let listener = tokio::net::TcpListener::bind(socket_address).await.unwrap();

let app = axum::Router::new().route("/api-docs/openapi.json", get(openapi));

axum::serve(listener, app.into_make_service())
.await
.unwrap()
}
7 changes: 4 additions & 3 deletions examples/todo-actix/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,11 @@ async fn main() -> Result<(), impl Error> {
SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-docs/openapi.json", openapi.clone()),
)
// There is no need to create RapiDoc::with_openapi because the OpenApi is served
// via SwaggerUi instead we only make rapidoc to point to the existing doc.
.service(RapiDoc::new("/api-docs/openapi.json").path("/rapidoc"))
// Alternative to above
// via SwaggerUi. Instead we only make rapidoc to point to the existing doc.
//
// If we wanted to serve the schema, the following would work:
// .service(RapiDoc::with_openapi("/api-docs/openapi2.json", openapi.clone()).path("/rapidoc"))
.service(RapiDoc::new("/api-docs/openapi.json").path("/rapidoc"))
})
.bind((Ipv4Addr::UNSPECIFIED, 8080))?
.run()
Expand Down
2 changes: 1 addition & 1 deletion examples/todo-actix/src/todo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use actix_web::{
HttpResponse, Responder,
};
use serde::{Deserialize, Serialize};
use utoipa::{ToSchema, IntoParams};
use utoipa::{IntoParams, ToSchema};

use crate::{LogApiKey, RequireApiKey};

Expand Down
26 changes: 26 additions & 0 deletions scripts/validate-examples.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

set -e

: "${CARGO:=cargo}"

# Finds examples in the `./examples` directory. This query will also automatically
# ignore directories that are not Rust projects (i.e. those that don't contain Cargo.toml).
EXAMPLES=$(find ./examples/ -maxdepth 1 -mindepth 1 -type d -exec test -e "{}/Cargo.toml" ";" -print)


for example in $EXAMPLES
do
echo "Checking example: $example..."

pushd $example

$CARGO fmt --check
echo " -> example is properly formatted (passes cargo fmt)"
$CARGO clippy --all-features --all-targets --workspace --quiet
echo " -> example compiles (passes cargo clippy)"

popd
done

echo "All examples are valid!"

0 comments on commit 8ab1e96

Please sign in to comment.