diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000..33df461 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,68 @@ +name: deploy-docs.yml +on: + push: + branches: + - "master" + workflow_dispatch: + +permissions: + id-token: write + pages: write + +env: + # Name of module and id separated by a slash + INSTANCE: Writerside/sd + # Replace HI with the ID of the instance in capital letters + ARTIFACT: webHelpSD2-all.zip + # Docker image version + DOCKER_VERSION: 241.15989 + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Build Writerside docs using Docker + uses: JetBrains/writerside-github-action@v4 + with: + instance: ${{ env.INSTANCE }} + artifact: ${{ env.ARTIFACT }} + docker-version: ${{ env.DOCKER_VERSION }} + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: artifact + path: artifacts/${{ env.ARTIFACT }} + retention-days: 7 + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + # Requires build job results + needs: build + runs-on: ubuntu-latest + + steps: + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: docs + + - name: Unzip artifact + run: unzip -O UTF-8 -qq ${{ env.ARTIFACT }} -d dir + + - name: Setup Pages + uses: actions/configure-pages@v4.0.0 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3.0.1 + with: + path: dir + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4.0.4 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d94f791..e543514 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -3,6 +3,9 @@ on: push: branches: [ "master" ] + paths: + - "**.cs" + - "**.yaml" env: REGISTRY: ghcr.io diff --git a/docs/.idea/.gitignore b/docs/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/docs/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/docs/.idea/docs.iml b/docs/.idea/docs.iml new file mode 100644 index 0000000..6102194 --- /dev/null +++ b/docs/.idea/docs.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/docs/.idea/modules.xml b/docs/.idea/modules.xml new file mode 100644 index 0000000..6049cfe --- /dev/null +++ b/docs/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/docs/.idea/vcs.xml b/docs/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/docs/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/docs/SS14.MapServer.swagger.json b/docs/SS14.MapServer.swagger.json new file mode 100644 index 0000000..b765527 --- /dev/null +++ b/docs/SS14.MapServer.swagger.json @@ -0,0 +1,1168 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "SS14.MapServer", + "version": "1.0" + }, + "paths": { + "/api/GitHubWebhook": { + "post": { + "tags": [ + "GitHubWebhook" + ], + "responses": { + "200": { + "description": "Success" + } + } + } + }, + "/api/Image/grid/{id}/{gridId}": { + "get": { + "tags": [ + "Image" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "gridId", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "image/jpg": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/webp": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/api/Image/grid/{id}/{gitRef}/{gridId}": { + "get": { + "tags": [ + "Image" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + }, + { + "name": "gitRef", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + }, + { + "name": "gridId", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "image/jpg": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/webp": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/api/Image/upload/{path}": { + "post": { + "tags": [ + "Image" + ], + "parameters": [ + { + "name": "path", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + } + }, + "encoding": { + "file": { + "style": "form" + } + } + } + } + }, + "responses": { + "200": { + "description": "Success" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "API_KEY": [ + "API" + ] + } + ] + } + }, + "/api/Image/file/{path}": { + "get": { + "tags": [ + "Image" + ], + "parameters": [ + { + "name": "path", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "image/jpg": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/webp": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + }, + "/api/Management/information": { + "get": { + "tags": [ + "Management" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InformationData" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "API_KEY": [ + "API" + ] + } + ] + } + }, + "/api/Management/statistics": { + "get": { + "tags": [ + "Management" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StatisticsData" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "API_KEY": [ + "API" + ] + } + ] + } + }, + "/api/Management/build/clean": { + "post": { + "tags": [ + "Management" + ], + "responses": { + "200": { + "description": "Success" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "API_KEY": [ + "API" + ] + } + ] + } + }, + "/api/Map": { + "get": { + "tags": [ + "Map" + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Map" + } + } + } + } + } + } + }, + "post": { + "tags": [ + "Map" + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "images": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + }, + "map": { + "type": "string" + } + } + }, + "encoding": { + "image": { + "style": "form" + }, + "map": { + "style": "form" + } + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Map" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "API_KEY": [ + "API" + ] + } + ] + } + }, + "/api/Map/list/{gitRef}": { + "get": { + "tags": [ + "Map" + ], + "parameters": [ + { + "name": "gitRef", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MapList" + } + } + } + } + } + } + }, + "/api/Map/{id}": { + "get": { + "tags": [ + "Map" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Map" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Map" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string", + "format": "uuid" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "API_KEY": [ + "API" + ] + } + ] + } + }, + "/api/Map/{id}/{gitRef}": { + "get": { + "tags": [ + "Map" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + }, + { + "name": "gitRef", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Map" + } + } + } + } + } + }, + "put": { + "tags": [ + "Map" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + }, + { + "name": "gitRef", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "images": { + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + }, + "map": { + "type": "string" + } + } + }, + "encoding": { + "image": { + "style": "form" + }, + "map": { + "style": "form" + } + } + } + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Map" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "API_KEY": [ + "API" + ] + } + ] + }, + "delete": { + "tags": [ + "Map" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + }, + { + "name": "gitRef", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "API_KEY": [ + "API" + ] + } + ] + } + }, + "/api/Map/sync": { + "post": { + "tags": [ + "Map" + ], + "parameters": [ + { + "name": "syncAll", + "in": "query", + "style": "form", + "schema": { + "type": "boolean" + } + }, + { + "name": "forceTiled", + "in": "query", + "style": "form", + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "responses": { + "200": { + "description": "Success" + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "API_KEY": [ + "API" + ] + } + ] + } + }, + "/api/Tile/{id}/{gridId}/{x}/{y}/{z}": { + "get": { + "tags": [ + "Tile" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "string", + "format": "uuid" + } + }, + { + "name": "gridId", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "x", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "y", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "z", + "in": "path", + "required": true, + "style": "simple", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "preload", + "in": "query", + "style": "form", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "image/jpg": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/png": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/webp": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Area": { + "type": "object", + "properties": { + "a": { + "$ref": "#/components/schemas/Point" + }, + "b": { + "$ref": "#/components/schemas/Point" + } + }, + "additionalProperties": false + }, + "GitConfiguration": { + "type": "object", + "properties": { + "repositoryUrl": { + "type": "string", + "nullable": true + }, + "branch": { + "type": "string", + "nullable": true + }, + "retrieveMapFilesFromDiff": { + "type": "boolean" + }, + "mapFilePatterns": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "mapFileExcludePatterns": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "dontRunWithCodeChanges": { + "type": "boolean" + }, + "codeChangePatterns": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "runOnPullRequests": { + "type": "boolean" + }, + "identity": { + "$ref": "#/components/schemas/GitIdentity" + }, + "sshCommand": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "GitIdentity": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "email": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "Grid": { + "required": [ + "extent", + "gridId" + ], + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid" + }, + "gridId": { + "type": "integer", + "format": "int32" + }, + "tiled": { + "type": "boolean" + }, + "tileSize": { + "type": "integer", + "format": "int32" + }, + "offset": { + "$ref": "#/components/schemas/Point" + }, + "extent": { + "$ref": "#/components/schemas/Area" + }, + "url": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "InformationData": { + "type": "object", + "properties": { + "version": { + "type": "string", + "nullable": true + }, + "runner": { + "type": "string", + "nullable": true + }, + "automatedBuilds": { + "type": "boolean", + "nullable": true + }, + "cleanRendererOutput": { + "type": "boolean", + "nullable": true + }, + "rendererOptions": { + "type": "string", + "nullable": true + }, + "directoryPoolSize": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "processQueueSize": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "gitConfiguration": { + "$ref": "#/components/schemas/GitConfiguration" + } + }, + "additionalProperties": false + }, + "LayerSource": { + "type": "object", + "properties": { + "url": { + "type": "string", + "nullable": true + }, + "extent": { + "$ref": "#/components/schemas/Area" + }, + "composition": { + "type": "string", + "nullable": true + }, + "parallaxScale": { + "$ref": "#/components/schemas/Point" + } + }, + "additionalProperties": false + }, + "Map": { + "required": [ + "displayName", + "gitRef", + "grids", + "mapId" + ], + "type": "object", + "properties": { + "mapGuid": { + "type": "string", + "format": "uuid" + }, + "gitRef": { + "minLength": 1, + "type": "string" + }, + "mapId": { + "minLength": 1, + "type": "string" + }, + "displayName": { + "minLength": 1, + "type": "string" + }, + "attribution": { + "type": "string", + "nullable": true + }, + "grids": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Grid" + }, + "readOnly": true + }, + "parallaxLayers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ParallaxLayer" + }, + "nullable": true + }, + "lastUpdated": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": false + }, + "MapList": { + "type": "object", + "properties": { + "maps": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MapListEntry" + }, + "nullable": true + } + }, + "additionalProperties": false + }, + "MapListEntry": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "id": { + "type": "string", + "nullable": true + } + }, + "additionalProperties": false + }, + "ParallaxLayer": { + "type": "object", + "properties": { + "scale": { + "$ref": "#/components/schemas/Point" + }, + "offset": { + "$ref": "#/components/schemas/Point" + }, + "static": { + "type": "boolean" + }, + "minScale": { + "type": "number", + "format": "float", + "nullable": true + }, + "source": { + "$ref": "#/components/schemas/LayerSource" + }, + "layers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LayerSource" + }, + "nullable": true + } + }, + "additionalProperties": false + }, + "Point": { + "type": "object", + "properties": { + "x": { + "type": "number", + "format": "float" + }, + "y": { + "type": "number", + "format": "float" + } + }, + "additionalProperties": false + }, + "StatisticsData": { + "type": "object", + "properties": { + "maps": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "grids": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "tiles": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "generalImages": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "queuedWork": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "imageFilesSize": { + "type": "integer", + "format": "int64", + "nullable": true + } + }, + "additionalProperties": false + } + }, + "securitySchemes": { + "API_KEY": { + "type": "apiKey", + "description": "API key must appear in header", + "name": "X-API-Key", + "in": "header" + } + } + } +} \ No newline at end of file diff --git a/docs/Writerside/cfg/buildprofiles.xml b/docs/Writerside/cfg/buildprofiles.xml new file mode 100644 index 0000000..eaa32e7 --- /dev/null +++ b/docs/Writerside/cfg/buildprofiles.xml @@ -0,0 +1,13 @@ + + + + + + + false + true + + + + diff --git a/docs/Writerside/redirection-rules.xml b/docs/Writerside/redirection-rules.xml new file mode 100644 index 0000000..1d71309 --- /dev/null +++ b/docs/Writerside/redirection-rules.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/docs/Writerside/sd.tree b/docs/Writerside/sd.tree new file mode 100644 index 0000000..2cc340c --- /dev/null +++ b/docs/Writerside/sd.tree @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/Writerside/topics/Basic-Example-Configuration.md b/docs/Writerside/topics/Basic-Example-Configuration.md new file mode 100644 index 0000000..326f337 --- /dev/null +++ b/docs/Writerside/topics/Basic-Example-Configuration.md @@ -0,0 +1,70 @@ +# Basic Example Configuration + +````yaml +Serilog: + Using: [ "Serilog.Sinks.Console" ] + MinimumLevel: + Default: "Information" + Override: + SS14: "Information" + Microsoft: "Warning" + Microsoft.Hosting.Lifetime: "Information" + Microsoft.AspNetCore: "Warning" + #This service doesn't use data protection + Microsoft.AspNetCore.DataProtection: "Error" + #Ignore api key spam + SS14.MapServer.Security.ApiKeyHandler: "Error" + + WriteTo: + - Name: Console + Args: + OutputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3} {SourceContext}] {Message:lj}{NewLine}{Exception}" + + Enrich: [ "FromLogContext" ] + +AllowedHosts: "*" + +Auth: + ApiKey: "" + +Git: + RepositoryUrl: "" + Branch: "master" + # Exclude maps that generally break the map renderer, + # like planet maps or you just don't want rendered + mapFileExcludePatterns: + - "europa.yml" + +Github: + AppName: "" + AppId: + AppPrivateKeyLocation: "private-key.pem" + AppWebhookSecret: "" + +ConnectionStrings: + default: "Server=map_database;Port=5432;Database=postgres;User Id=postgres;Password=;" + +Server: + CorsOrigins: + - "" + - "127.0.0.1" + Host: "" + EnableSentry: true + EnableSentryTracing: true + +# The sentry integration is entirely optional +Sentry: + Dsn: "" + EnableTracing: true + MaxRequestBodySize: "Always" + ServerName: "Live server" + # Ensure to keep this too false to prevent GDPR issues + SendDefaultPii: false + MinimumBreadcrumbLevel: "Warning" + MinimumEventLevel: "Error" + AttachStackTrace: true + DiagnosticsLevel: "Error" + +Build: + MapRendererCommand: "Content.MapRenderer" +```` \ No newline at end of file diff --git a/docs/Writerside/topics/Build-Configuration.md b/docs/Writerside/topics/Build-Configuration.md new file mode 100644 index 0000000..abf960d --- /dev/null +++ b/docs/Writerside/topics/Build-Configuration.md @@ -0,0 +1,97 @@ +# Build Configuration + +The build configuration section dictates if, how and where the map renderer is built and run. +Most configuration values in this section shouldn't be changed except for [MapRendererCommand](#maprenderercommand) and +possibly [ProcessTimeoutMinutes](#processtimeoutminutes). + +```yaml +Build: + [[[Enabled|#enabled]]]: [true|false] + [[[Runner|#runner]]]: + [[[RelativeOutputPath|#relativeoutputpath]]]: + [[[MapRendererProjectName|#maprendererprojectname]]]: + [[[MapRendererCommand|#maprenderercommand]]]: + [[[MapRendererOptionsString|#maprendereroptionsstring]]]: + [[[ProcessTimeoutMinutes|#processtimeoutminutes]]]: + [[[RelativeMapFilesPath|#relativemapfilespath]]]: + [[[MapDataFileName|#mapdatafilename]]]: + [[[CleanMapFolderAfterImport|#cleanmapfolderafterimport]]]: [true|false] +``` + +## Configuration Options + +### Enabled +`[true|false] default=true` + +Disables fetching and building the game content. +The map server can only be used to host map images if building is disabled. + + +### Runner +` default=Local` + +The type of runner to use. + +#### Possible values: + +Local +: Builds and executes the map renderer locally. +Requires the correct dotnet version to be installed on the host. + +Container +: Uses a docker container for building and executing the map renderer. + +> Currently ony `Local` is supported. +{style="note"} + +### RelativeOutputPath +` default="bin"` + +The output path relative to the runner specific build directory. + +### MapRendererProjectName +` default="Content.MapRenderer"` + +The name of the C# project that contains the map renderer. + +### MapRendererCommand +` default="Content.MapRenderer.exe"` + +The command to execute for rendering maps. + +> This needs to be `Content.MapRenderer` on linux +{style="note"} + +### MapRendererOptionsString +` default="--format webp --viewer -f"` + +The options provided to the map renderer command when rendering maps. + +### ProcessTimeoutMinutes +` default="10"` + +The time the build and render process can run before getting timed out. + +> Building the game and running the map renderer take a while. The timeout shouldn't be set to low. + +### RelativeMapFilesPath +` default="Resources/MapImages"` + +The path the rendered map images end up after running the map renderer. Relative to the runners build directory. + +### MapDataFileName +` default="map.json"` + +The name of the json file that gets generated for each map containing information about them. + +### CleanMapFolderAfterImport +`[true|false] default=true` + +Controls whether the contents of the [RelativeMapFilesPath](#relativemapfilespath)should be +deleted after ingesting the rendered map images. + +This is enabled to save space on the hardrive but can be disabled to allow other programs to use the generated map images. + + + + \ No newline at end of file diff --git a/docs/Writerside/topics/Configuration-Reference.topic b/docs/Writerside/topics/Configuration-Reference.topic new file mode 100644 index 0000000..59133d1 --- /dev/null +++ b/docs/Writerside/topics/Configuration-Reference.topic @@ -0,0 +1,30 @@ + + + + + + Configuration Reference + a + + + + + + Configuration Sections + + + + + + + + + + Configuration Examples + + + + \ No newline at end of file diff --git a/docs/Writerside/topics/Container-Configuration.md b/docs/Writerside/topics/Container-Configuration.md new file mode 100644 index 0000000..f35d240 --- /dev/null +++ b/docs/Writerside/topics/Container-Configuration.md @@ -0,0 +1,21 @@ +# Container Configuration + +This section contains the configuration for the container runner. +The container runner is not implemented yet so setting any of these doesn't make sense. + +````yaml +Container: + [[[DockerHost|#dockerhost]]]: +```` + +## Configuration Options + +### DockerHost +`` + +The docker host url used to access the docker api for creating and stopping containers. +This needs to be a valid url. + + + + \ No newline at end of file diff --git a/docs/Writerside/topics/File-Paths-Configuration.md b/docs/Writerside/topics/File-Paths-Configuration.md new file mode 100644 index 0000000..7f0267d --- /dev/null +++ b/docs/Writerside/topics/File-Paths-Configuration.md @@ -0,0 +1,36 @@ +# File Paths Configuration + +The file paths configuration sections contains all of the different paths used for storing map data. + +````yaml +FilePaths: + [[[GridImagesPath|#gridimagespath]]]: + [[[ImagesPath|#imagespath]]]: + [[[TilesPath|#tilespath]]]: + [[[TemporaryFilesPath|#temporaryfilespath]]]: +```` + +## Configuration Options +### GridImagesPath +` default="data/grid_images` + +Fill size map grid images. + +### ImagesPath +` default="data/images` + +General images either generated by the map server, like image diffs, or uploaded through the api. + +### TilesPath +` default="data/tiles` + +Map grid tile images generated for the map viewers tiling mode. + +### TemporaryFilesPath +` default="data/tmp` + +General temporary files. + + + + \ No newline at end of file diff --git a/docs/Writerside/topics/Git-Configuration.md b/docs/Writerside/topics/Git-Configuration.md new file mode 100644 index 0000000..da10444 --- /dev/null +++ b/docs/Writerside/topics/Git-Configuration.md @@ -0,0 +1,98 @@ +# Git Configuration + +This section contains all the settings related to working with the content git repository. + +> Be carefull when changing configuration settings in this section as some are relevant for the servers security +{style="note"} + +````yaml +yaml: + [[[RepositoryUrl|#repositoryurl]]]: + [[[Branch|#branch]]]: + [[[RetrieveMapFilesFromDiff|#retrievemapfilesfromdiff]]]: [true|false] + [[[MapFilePatterns|#mapfilepatterns]]]: + [[[MapFileExcludePatterns|#mapfileexcludepatterns]]]: + [[[DontRunWithCodeChanges|#dontrunwithcodechanges]]]: [true|false] + [[[CodeChangePatterns|#codechangepatterns]]]: + [[[RunOnPullRequests|#runonpullrequests]]]: [true|false] + [[[Identity|#identity]]]: + Name: + Email: + [[[SshCommand|#sshcommand]]]: +```` + +## Configuration Options +### RepositoryUrl + +The url for the git repository to pull from. +This needs to be a valid url. + +> Be sure that this is a repository you can trust not to have malicious code on the branch specified in [Branch](#branch). +{style="warning"} + +### Branch +` default="master"` + +The default branch to pull changes from when a run is triggered. + +### RetrieveMapFilesFromDiff +`[true|false] default=true` + +If true the map server will retrieve the list of changed maps from the github diff api. +If this is false all maps will get updated on every push. + +> Requires the map server to be installed as a github app. +> {style="note"} + +### MapFilePatterns +` default="master"` + +Glob patterns of map files to check for. + +### MapFileExcludePatterns +`` + +Glob patterns for excluding specific map files. + +### DontRunWithCodeChanges +`[true|false] default=true` + +Prevent updating maps when there where any c# files changed. + +> Requires the map server to be installed as a github app. +> This setting is recommended when the map server is configured to run for PRs +> as it prevents potentially malicious changes from being built and executed. +> {style="note"} + +> Be **very** careful about turning this off as it may allow arbitrary code execution +> if the map server is not configured with this option being turned off in mind! +> {style="warning"} + +### CodeChangePatterns +` default=["**/*.cs"]` + +Glob patterns used for detecting code changed. + +### RunOnPullRequests +`[true|false] default=true` + +Setting this to true enables listening to the PullRequest event for putting the rendered map as a comment into the PR. + +### Identity +` default={Name="ss14.mapserver", Email="git@mapserver.localhost"}` + +The identity git will use to pull changes with. This doesn't have an effect on anything but is required for pulling +changes in some situations. + +### SshCommand +`` + +The ssh command used by git if set. Used for providing an ssh key to use. + +````Shell +ssh -i [path to ssh key] +```` + + + + \ No newline at end of file diff --git a/docs/Writerside/topics/Github-Configuration.md b/docs/Writerside/topics/Github-Configuration.md new file mode 100644 index 0000000..42c874b --- /dev/null +++ b/docs/Writerside/topics/Github-Configuration.md @@ -0,0 +1,43 @@ +# GitHub Configuration + +The GitHub configuration section contains settings required to set up integration with GitHub. + +````yaml +yaml: + [[[Enabled|#enabled]]]: [true|false] + [[[AppName|#appname]]]: + [[[AppPrivateKeyLocation|#appprivatekeylocation]]]: + [[[AppId|#appid]]]: + [[[TemplateLocation|#templatelocation]]]: +```` + +## Configuration Options +### Enabled +`[true|false] default=true` + +Enables GitHub integration. If this is set to false Posting on PRs and checking changed files doesn't work. +Setting this to disabled requires GitHub Webhooks to be set up if you still want automatic map rendering. + +### AppName +`` + +The name of the GitHub app. + +### AppPrivateKeyLocation +`` + +The path to the private key file created when setting up the GitHubApp- + +### AppId +`` + +The app id of the GitHub app + +### TemplateLocation +`` + +The location of liquid templates used for GitHub PR comments. + + + + \ No newline at end of file diff --git a/docs/Writerside/topics/Processing-Configuration.md b/docs/Writerside/topics/Processing-Configuration.md new file mode 100644 index 0000000..3abc930 --- /dev/null +++ b/docs/Writerside/topics/Processing-Configuration.md @@ -0,0 +1,38 @@ +# Processing Configuration + +Settings related to processing maps. + +````yaml +yaml: + [[[DirectoryPoolMaxSize|#directorypoolmaxsize]]]: + [[[TargetDirectory|#targetdirectory]]]: + [[[ProcessQueueMaxSize|#processqueuemaxsize]]]: + [[[JunkFilePatterns|#junkfilepatterns]]]: +```` + +## Configuration Options +### DirectoryPoolMaxSize +` default=3` + +The maximum size of the process directory pool. +This means that no more than the given amount of directories will be created +and it in turn dictates the maximum amount of processes that can run in parallel. + +### TargetDirectory +`` + +This is the target directory for creating the process directory pool. + +### ProcessQueueMaxSize +` default=6` + +The maximum amount of processes that can be queued up before new process requests will be rejected. + +### JunkFilePatterns +`` + +Glob patterns for files that should be deleted from build directories when getting cleaned. + + + + \ No newline at end of file diff --git a/docs/Writerside/topics/Quickstart.md b/docs/Writerside/topics/Quickstart.md new file mode 100644 index 0000000..fe05468 --- /dev/null +++ b/docs/Writerside/topics/Quickstart.md @@ -0,0 +1,99 @@ +# Quickstart + +%project-name% can automatically pull a SS14 git repository, build it and run the map renderer. +It also takes care of managing and hosting map images. + +It's mainly used in combination with the map viewer, which lists and displays maps from a specific branch: +[https://github.com/juliangiebel/space-station-14-map-viewer](https://github.com/juliangiebel/space-station-14-map-viewer) + +The map viewer for Official SS14 servers can be found here: [https://maps14.tanukij.dev/](https://maps14.tanukij.dev/) + +The map server can also post map images on PRs that modify map files. That requires setting up a Github app. + +> **The map server is not required for running the viewer** +> +> You can run the viewer by serving the map images and the required json files as static files +> +{style="note"} + +## Requirements + +There are some requirements for running a map server instance. +With the manual rendering setup you can trigger rendering map images by making an api request. +If you want automatic rendering and map images under PRs changing map files you'll need to set up a Github app. + +### Manual rendering and hosting maps only: +- A public git repository + - Private submodules are supported but the content repo needs to be public +- Docker or .net 8 or higher +- A domain (for https) +- A reverse proxy is recommended +- Postgres database + +### Automatic rendering, hosting and comments on PRs: +- All of the above requirements +- The repo needs to be on Github +- [A github app](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app) + +## Setup - Docker compose + +There is a docker image provided for %project-name%: +[https://github.com/juliangiebel/SS14.MapServer/pkgs/container/ss14.mapserver](https://github.com/juliangiebel/SS14.MapServer/pkgs/container/ss14.mapserver) + +````yaml +# Example docker compose file +version: '3.3' +services: + # The ss14 map server container doesn't support https on its own. + # Please use a reverse proxy + ss14mapserver: + image: ghcr.io/juliangiebel/ss14.mapserver:latest + volumes: + - ./appsettings.yaml:/app/appsettings.yaml + - ./private-key.pem:/app/private-key.pem + - ./files:/app/data + - ./build:/app/build + ports: + - 5218:80 # Replace 5218 with the port you need + # Disables core dumps to prevent map renderer crashes from filling + # up your hard drive with over a gigabyte per dump + ulimits: + core: + hard: 0 + soft: 0 + map_database: + image: postgres:latest + environment: + # Replace postgres with a randomly generated password + - POSTGRES_PASSWORD=postgres + volumes: + - ./data:/var/lib/postgresql/data + - ./init.sql:/docker-entrypoint-initdb.d/init.sql +```` +{collapsible="true"} + +## Setup - Manual + +> Don't set %project-name% up without docker while using local mode and having automated builds enabled. +> You run the risk of malicious code making its way into the content repo and being executed on the host machine. +{style="warning"} + +*Todo: setup guide for running the map server without docker* + +## Reverse proxy +It is recommended to run a reverse proxy in front of %project-name%. +The official map renderer instance is using [Caddy](https://caddyserver.com/) + +### Example Caddy configuration +```` +mapserver.tanukij.dev { + encode zstd gzip + reverse_proxy 127.0.0.1:8956 + + import cors https://maps14.tanukij.dev +} +```` + + +## Configuration + diff --git a/docs/Writerside/topics/SS14.MapServer.swagger.json/API_Reference.md b/docs/Writerside/topics/SS14.MapServer.swagger.json/API_Reference.md new file mode 100644 index 0000000..1fca7ab --- /dev/null +++ b/docs/Writerside/topics/SS14.MapServer.swagger.json/API_Reference.md @@ -0,0 +1,5 @@ +# API Reference +*Todo: Add descriptions to openapi spec* +[Postman Workspace](https://www.postman.com/juliangiebel/workspace/ss14-mapserver/overview) + + \ No newline at end of file diff --git a/docs/Writerside/topics/Server-Configuration.md b/docs/Writerside/topics/Server-Configuration.md new file mode 100644 index 0000000..d580e82 --- /dev/null +++ b/docs/Writerside/topics/Server-Configuration.md @@ -0,0 +1,81 @@ +# Server Configuration + + + +````yaml +yaml: + [[[Host|#host]]]: + [[[CorsOrigins|#corsorigins]]]: + [[[Language|#language]]]: + [[[UseHttps|#usehttps]]]: [true|false] + [[[UseForwardedHeaders|#useforwardedheaders]]]: [true|false] + [[[PathBase|#pathbase]]]: + [[[RateLimitCount|#ratelimitcount]]]: + [[[RateLimitWindowMinutes|#ratelimitwindowminutes]]]: + [[[EnableSentry|#enablesentry]]]: [true|false] + [[[EnableSentryTracing|#enablesentrytracing]]]: [true|false] +```` + +## Configuration Options +### Host +` default="https://localhost:7154` + +The URL the map server is hosted behind. + +### CorsOrigins +`` + +A list of allowed cors origins. + +### Language +` default="en-us"` + +The locale the map server should use. + +### UseHttps +`[true|false] default=false` + +Enables https redirection if true. Set this to false if run behind a reverse proxy. + +### UseForwardedHeaders +`[true|false] default=true` + +Enables support for reverse proxy headers like "X-Forwarded-Host" if true. Set this to true if run behind a reverse proxy. + +### PathBase +`` + +Sets the request base path used before any routes apply i.e. "/base/api/Maps" with "/base" being the PathBase. +Set this if run behind a reverse proxy on a sub path and the proxy doesn't strip the path the server is hosted on. + +> Add a slash before the path: "/path". +{style="note"} + +### RateLimitCount +` default = 20` + +The amount of requests allowed by per client inside the rate limit window. + +### RateLimitWindowMinutes +` default=1` + +The amount of time before the rate limit replenishes. +%project-name% is using a fixed window rate limiter. + + +### EnableSentry +`[true|false] default=false` + +Whether the Sentry integration is enabled or not. + +> Configure sentry using the `Sentry` configuration section and any configuration options provided by Sentry. +> [https://docs.sentry.io/platforms/dotnet/configuration](https://docs.sentry.io/platforms/dotnet/configuration) + +### EnableSentryTracing +`[true|false] default=false` + +Enables sentries performance monitoring on endpoints if Sentry is enabled. + + + + \ No newline at end of file diff --git a/docs/Writerside/v.list b/docs/Writerside/v.list new file mode 100644 index 0000000..931e13e --- /dev/null +++ b/docs/Writerside/v.list @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/docs/Writerside/writerside.cfg b/docs/Writerside/writerside.cfg new file mode 100644 index 0000000..2aee14a --- /dev/null +++ b/docs/Writerside/writerside.cfg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file