Skip to content

Commit

Permalink
Merge pull request #5 from mrtz-j/develop
Browse files Browse the repository at this point in the history
Add CI to Build and Publish and Update Documentation
  • Loading branch information
nojaf authored Aug 5, 2024
2 parents 402a3c2 + 41ab16a commit 710ffa4
Show file tree
Hide file tree
Showing 10 changed files with 318 additions and 49 deletions.
17 changes: 0 additions & 17 deletions .github/dependabot.yaml

This file was deleted.

63 changes: 63 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Build

on:
push:
pull_request:

env:
# Stop wasting time caching packages
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
# Disable sending usage data to Microsoft
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_VERSION: 8.0.301

# Kill other jobs when we trigger this workflow by sending new commits
# to the PR.
# https://stackoverflow.com/a/72408109
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
fantomas-check:
name: "Format with Fantomas"
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

- name: Tool Restore
run: dotnet tool restore

- name: Lint
run: dotnet fantomas -r --check .

build:
name: Build the project
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
steps:
- name: Checkout repository
uses: actions/checkout@v4

# workaround for https://github.com/actions/runner/issues/2033
- name: ownership workaround
run: git config --global --add safe.directory '*'

- name: Setup .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}

- name: Restore nuget dependencies
run: dotnet restore

- name: Build
run: dotnet build -c Release --no-restore
73 changes: 73 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Publish

on:
push:
pull_request:
release:
types:
- published

env:
# Stop wasting time caching packages
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
# Disable sending usage data to Microsoft
DOTNET_CLI_TELEMETRY_OPTOUT: true
# Project name to pack and publish
PROJECT_NAME: Giraffe.OpenApi
DOTNET_VERSION: 8.0.301
# GitHub Packages Feed settings
GITHUB_FEED: https://nuget.pkg.github.com/giraffe-fsharp/
GITHUB_USER: dustinmoris
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Official NuGet Feed settings
NUGET_FEED: https://api.nuget.org/v3/index.json
NUGET_KEY: ${{ secrets.NUGET_KEY }}

jobs:
build:
name: Build the project
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Release --no-restore

deploy:
name: Publish a new version
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Create Release NuGet package
run: |
arrTag=(${GITHUB_REF//\// })
VERSION="${arrTag[2]}"
echo Version: $VERSION
VERSION="${VERSION//v}"
echo Clean Version: $VERSION
dotnet pack -v normal -c Release --include-symbols --include-source -p:PackageVersion=$VERSION -o nupkg src/$PROJECT_NAME/$PROJECT_NAME.*proj
- name: Push to GitHub Feed
run: |
for f in ./nupkg/*.nupkg
do
echo $f
curl -vX PUT -u "$GITHUB_USER:$GITHUB_TOKEN" -F package=@$f $GITHUB_FEED
done
- name: Push to NuGet Feed
run: dotnet nuget push ./nupkg/*.nupkg --source $NUGET_FEED --skip-duplicate --api-key $NUGET_KEY
21 changes: 1 addition & 20 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,26 +1,6 @@
<Project>
<PropertyGroup>
<!-- Common packaging properties for all packages in this repo -->
<Authors>Moritz Jörg</Authors>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Copyright>Copyright © $([System.DateTime]::UtcNow.Year)</Copyright>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<DebugType>embedded</DebugType>
<Description>OpenApi support for Giraffe</Description>
<RepositoryUrl>https://github.com/mrtz-j/Giraffe.OpenApi</RepositoryUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/mrtz-j/Giraffe.OpenApi/src/Giraffe.OpenApi</PackageProjectUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>Giraffe;ASP.NET Core;F#;FSharp;Http;Web;OpenApi</PackageTags>
<PackageReadmeFile>README.md</PackageReadmeFile>
<Version>0.0.1</Version>
<PackageVersion>0.0.1</PackageVersion>
<PackageReleaseNotes>Initial Version</PackageReleaseNotes>
</PropertyGroup>

<PropertyGroup>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
<!-- https://www.gresearch.co.uk/blog/article/improve-nuget-restores-with-static-graph-evaluation/ -->
<RestoreUseStaticGraphEvaluation>true</RestoreUseStaticGraphEvaluation>
Expand All @@ -31,6 +11,7 @@
</PropertyGroup>

<ItemGroup>
<!-- Analyzers -->
<PackageReference Include="FSharp.Analyzers.Build" PrivateAssets="All">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>build</IncludeAssets>
Expand Down
136 changes: 133 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,137 @@
![Giraffe](https://raw.githubusercontent.com/giraffe-fsharp/Giraffe/master/giraffe.png)

# Giraffe.OpenApi

> [!IMPORTANT]
> This is currently only works with my branch of Giraffe, which can be found [here](https://github.com/mrtz-j/Giraffe/tree/configureEndpoint).
An extension for the [Giraffe](https://github.com/giraffe-fsharp/Giraffe) Web Application framework with functionality to auto generate OpenApi documentation spec from code.

[![NuGet Info](https://buildstats.info/nuget/Giraffe.OpenApi?includePreReleases=true)](https://www.nuget.org/packages/Giraffe.OpenApi/)


## Table of Contents

- [About](#about)
- [Getting Started](#getting-started)
- [Documentation](#documentation)
- [Integration](#integration)
- [addOpenApi](#addopenapi)
- [addOpenApiSimple](#addopenapisimple)
- [configureEndpoint](#configureendpoint)
- [License](#license)

## About

`Giraffe.OpenApi` is a library that extends the `Giraffe` Web Application framework with functionality to auto generate OpenApi documentation spec from code. This means that you can define your API endpoints using Giraffe and generate OpenApi or Swagger documentation from it.

Inspired by the [Oxpecker.OpenApi](https://github.com/Lanayx/Oxpecker/blob/develop/src/Oxpecker.OpenApi) library, but adapted to work with Giraffe.

## Getting Started

Add the `Giraffe.OpenApi` NuGet package to your project:

```bash
dotnet add package Giraffe.OpenApi
```

Two use cases:

```fsharp
open Giraffe
open Giraffe.EndpointRouting
open Giraffe.OpenApi
let endpoints = [
// addOpenApi supports passing detailed configuration
POST [
route "/product" (text "Product posted!")
|> addOpenApi (OpenApiConfig(
requestBody = RequestBody(typeof<Product>),
responseBodies = [| ResponseBody(typeof<string>) |],
configureOperation = (fun o -> o.OperationId <- "PostProduct"; o)
))
]
// addOpenApiSimple is a shortcut for simple cases
GET [
routef "/product/{%i}" (
fun id ->
forecases
|> Array.find (fun f -> f.Id = num)
|> json
)
|> configureEndpoint _.WithName("GetProduct")
|> addOpenApiSimple<int, Product>
]
]
```

## Documentation

### Integration

Since `Giraffe.OpenApi` works on top of `Microsoft.AspNetCore.OpenApi` and `Swashbuckle.AspNetCore` packages, you need to do [standard steps](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/openapi):

```fsharp
let configureApp (appBuilder: IApplicationBuilder) =
appBuilder
.UseRouting()
.UseSwagger() // For generating OpenApi spec
.UseSwaggerUI() // For viewing Swagger UI
.UseGiraffe(endpoints)
.UseGiraffe(notFoundHandler)
let configureServices (services: IServiceCollection) =
services
.AddRouting()
.AddGiraffe()
.AddEndpointsApiExplorer() // Use the API Explorer to discover and describe endpoints
.AddSwaggerGen() // Swagger dependencies
|> ignore
```

To make endpoints discoverable by Swagger, you need to call one of the following functions: `addOpenApi` or `addOpenApiSimple` on the endpoint.

_NOTE: you don't have to describe routing parameters when using those functions, they will be inferred from the route template automatically._

### addOpenApi

This method is used to add OpenApi metadata to the endpoint. It accepts `OpenApiConfig` object with the following optional parameters:

```fsharp
type OpenApiConfig (?requestBody : RequestBody,
?responseBodies : ResponseBody seq,
?configureOperation : OpenApiOperation -> OpenApiOperation) =
// ...
```

Response body schema will be inferred from the types passed to `requestBody` and `responseBodies` parameters. Each `ResponseBody` object in sequence must have different status code.

`configureOperation` parameter is a function that allows you to do very low-level modifications the `OpenApiOperation` object.

### addOpenApiSimple

This method is a shortcut for simple cases. It accepts two generic type parameters - request and response, so the schema can be inferred from them.

```fsharp
let addOpenApiSimple<'Req, 'Res> = ...
```

If your handler doesn't accept any input, you can pass `unit` as a request type (works for response as well).

### configureEndpoint

The two methods above return `Endpoint` object, which can be further configured using `configureEndpoint` method provided by [Giraffe](https://github.com/giraffe-fsharp/Giraffe). It accepts `Endpoint` object and returns the same object, so you can chain multiple calls.

```fsharp
let endpoints = [
GET [
route "/hello" (text "Hello, World!")
|> configureEndpoint _.WithName("HelloWorld")
|> configureEndpoint _.WithDescription("Simple hello world endpoint")
|> configureEndpoint _.WithSummary("Hello world")
|> addOpenApiSimple<unit, string>
]
]
```

Auto generate an API documentation for Giraffe Web Applications using OpenApi
## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
6 changes: 3 additions & 3 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pipeline "Build" {
async {
let deleteIfExists folder =
if Directory.Exists folder then
Directory.Delete (folder, true)
Directory.Delete(folder, true)

deleteIfExists packageOutput
deleteIfExists (__SOURCE_DIRECTORY__ </> "output")
Expand Down Expand Up @@ -60,11 +60,11 @@ pipeline "Analyze" {
runIfOnlySpecified true
}


pipeline "Publish" {
workingDir __SOURCE_DIRECTORY__
stage "publish" {
run "dotnet publish --nologo -c Release --ucr -p:PublishReadyToRun=true ./src/Giraffe.OpenApi/Giraffe.OpenApi.fsproj"
run
"dotnet publish --nologo -c Release --ucr -p:PublishReadyToRun=true ./src/Giraffe.OpenApi/Giraffe.OpenApi.fsproj"
}
runIfOnlySpecified true
}
Expand Down
Binary file added giraffe-64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 710ffa4

Please sign in to comment.