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
70 changes: 70 additions & 0 deletions .github/workflows/pr-gatechecks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: PR Gatechecks

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
build:
#name: Build Solution
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'

- name: Restore
run: dotnet restore

- name: Build
run: dotnet build --no-restore --configuration Release

#analyze-openapi:
#name: Analyze OpenAPI Spec
#runs-on: ubuntu-latest

#steps:
- name: Analyze OpenAPI
id: analyze
uses: ApyGuard/apyguard_openapi_analysis@v1.0.9
with:
file: ${{ github.workspace }}/src/CheersDb.Api/CheersDb.Api.json
output_format: json

- name: Display Results
run: |
echo "OpenAPI Analysis Results:"
echo "========================="
echo "Valid: ${{ steps.analyze.outputs.is_valid }}"
echo "Suggestions: ${{ steps.analyze.outputs.suggestions_count }}"
echo "Operations: ${{ steps.analyze.outputs.operations_count }}"
echo "Paths: ${{ steps.analyze.outputs.paths_count }}"
echo "Schemas: ${{ steps.analyze.outputs.schemas_count }}"

- name: Comment on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const analysis = JSON.parse('${{ steps.analyze.outputs.analysis }}');
const comment = `## 🔍 OpenAPI Analysis Results

**Valid**: ${analysis.is_valid ? '✅' : '❌'}
**Total Suggestions**: ${analysis.suggestions ? Object.values(analysis.suggestions).reduce((total, suggestions) => total + suggestions.length, 0) : 0}
**Operations**: ${analysis.summary ? analysis.summary.operations_count : 0}
**Paths**: ${analysis.summary ? analysis.summary.paths_count : 0}
**Schemas**: ${analysis.summary ? analysis.summary.schemas_count : 0}
`;


github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
7 changes: 7 additions & 0 deletions CheersDb.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Solution>
<Folder Name="/Solution Items/">
<File Path="Directory.build.props" />
<File Path="Directory.Packages.props" />
</Folder>
<Project Path="src/CheersDb.Api/CheersDb.Api.csproj" />
</Solution>
10 changes: 10 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project>
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>14.0</LangVersion>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<Nullable>enable</Nullable>
<TargetFramework>net10.0</TargetFramework>
<Version>0.0.1</Version>
</PropertyGroup>
</Project>
11 changes: 11 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="10.0.9" />
<PackageVersion Include="Microsoft.Extensions.ApiDescription.Server" Version="10.0.9" />
<PackageVersion Include="Microsoft.OpenApi" Version="2.9.0" />
<PackageVersion Include="Scalar.AspNetCore" Version="2.16.3" />
</ItemGroup>
</Project>
14 changes: 14 additions & 0 deletions src/CheersDb.Api/AppSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Microsoft.OpenApi;

namespace CheersDb.Api;

/// <summary>
/// Represents the application settings for the CheersDb API.
/// </summary>
public class AppSettings
{
/// <summary>
/// Gets the OpenAPI information for the API, such as title, version, and description.
/// </summary>
public OpenApiInfo? OpenApiInfo { get; init; }
}
20 changes: 20 additions & 0 deletions src/CheersDb.Api/CheersDb.Api.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<OpenApiDocumentsDirectory>$(MSBuildProjectDirectory)</OpenApiDocumentsDirectory>
<OpenApiGenerateDocuments>true</OpenApiGenerateDocuments>
<OpenApiGenerateDocumentsOnBuild>true</OpenApiGenerateDocumentsOnBuild>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
<PackageReference Include="Microsoft.Extensions.ApiDescription.Server">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.OpenApi" />
<PackageReference Include="Scalar.AspNetCore" />
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions src/CheersDb.Api/CheersDb.Api.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@CheersDb.Api_HostAddress = http://localhost:5104

GET {{CheersDb.Api_HostAddress}}/producers/1
Accept: application/json

###
184 changes: 184 additions & 0 deletions src/CheersDb.Api/CheersDb.Api.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
{
"openapi": "3.1.1",
"info": {
"title": "CheersDb API",
"description": "An API for retrieving and altering breweries on the CheersDb platform",
"version": "v1"
},
"paths": {
"/producers/{id}": {
"get": {
"tags": [
"Producers"
],
"summary": "Retrieves details for a specific producer by id",
"operationId": "GetProducerDetails",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The id of the producer to retrieve",
"required": true,
"schema": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"type": "integer",
"format": "int32"
}
}
],
"responses": {
"200": {
"description": "Returns the requested producer in the response body",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetProducerDetailsDto"
}
}
}
},
"404": {
"description": "Indicates the requested producer was not found, or the URI is invalid",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
},
"500": {
"$ref": "#/components/responses/InternalServerError"
}
}
}
}
},
"components": {
"schemas": {
"GetProducerDetailsDto": {
"type": "object",
"properties": {
"id": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"type": [
"null",
"integer",
"string"
],
"description": "The id of the producer",
"format": "int32",
"example": 328
},
"name": {
"type": [
"null",
"string"
],
"description": "The name of the producer",
"example": "Rye River Brewing"
},
"links": {
"type": [
"null",
"array"
],
"items": {
"$ref": "#/components/schemas/LinkDto"
},
"description": "Links related to the producer, such as a self link to retrieve the producer details",
"example": [
{
"rel": "self",
"href": "/producers/328",
"method": "GET"
}
]
}
},
"description": "Details about a producer"
},
"LinkDto": {
"required": [
"rel",
"href",
"method"
],
"type": "object",
"properties": {
"rel": {
"type": "string",
"description": "The relationship of the link to the current resource",
"example": "self"
},
"href": {
"type": "string",
"description": "The URL of the link",
"example": "/producers/1"
},
"method": {
"type": "string",
"description": "The HTTP method for the link",
"example": "GET"
}
},
"description": "Represents a hypermedia link in the API response, providing information about the relationship, URL, and HTTP method for the link."
},
"ProblemDetails": {
"type": "object",
"properties": {
"type": {
"type": [
"null",
"string"
]
},
"title": {
"type": [
"null",
"string"
]
},
"status": {
"pattern": "^-?(?:0|[1-9]\\d*)$",
"type": [
"null",
"integer",
"string"
],
"format": "int32"
},
"detail": {
"type": [
"null",
"string"
]
},
"instance": {
"type": [
"null",
"string"
]
}
}
}
},
"responses": {
"InternalServerError": {
"description": "Indicates that an unexpected internal server error has occurred",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProblemDetails"
}
}
}
}
}
},
"tags": [
{
"name": "Producers"
}
]
}
41 changes: 41 additions & 0 deletions src/CheersDb.Api/Controllers/ProducersController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using CheersDb.Api.Dtos;
using CheersDb.Api.Http;
using Microsoft.AspNetCore.Mvc;
using System.Net.Mime;

namespace CheersDb.Api.Controllers;

/// <summary>
/// Controller for managing producers in the CheersDb API.
/// </summary>
[ApiController]
[Route("[controller]")]
[Produces(MediaTypeNames.Application.Json)]
public class ProducersController : ControllerBase
{
/// <summary>
/// Retrieves details for a specific producer by id
/// </summary>
/// <param name="id">The id of the producer to retrieve</param>
/// <returns>The requested producer details</returns>
[HttpGet("{id:int}", Name = nameof(GetProducerDetails))]
[ProducesResponseType(typeof(GetProducerDetailsDto), StatusCodes.Status200OK, Description = "Returns the requested producer in the response body")]
[ProducesResponseType(StatusCodes.Status404NotFound, Description = "Indicates the requested producer was not found, or the URI is invalid")]
public IActionResult GetProducerDetails([FromRoute] int id)
{
return Ok(new GetProducerDetailsDto()
{
Id = id,
Name = "Producer Name",
Links =
[
new()
{
Rel = LinkRels.Self,
Href = Url.RouteUrl(nameof(GetProducerDetails), new { id }) ?? string.Empty,
Method = HttpMethod.Get.ToString()
}
]
});
}
}
Loading
Loading