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
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
./*
!release/
29 changes: 0 additions & 29 deletions .github/workflows/publish-changelog.yml

This file was deleted.

45 changes: 0 additions & 45 deletions .github/workflows/publish-testing.yml

This file was deleted.

117 changes: 89 additions & 28 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,118 @@ name: Publish

on:
workflow_dispatch:
# Frontier: re-enabled autopublish bawk
push:
tags:
- 'v*.*.*-*'
- 'v*.*.*'

concurrency:
group: publish
cancel-in-progress: false

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/monolith-server

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write

outputs:
image_tag: ${{ steps.meta.outputs.tags }}
image_digest: ${{ steps.build.outputs.digest }}

steps:
- name: Install dependencies
run: sudo apt-get install -y python3-paramiko python3-lxml

- uses: actions/checkout@v3.6.0
steps:
- uses: actions/checkout@v4
with:
submodules: 'recursive'

- name: Extract version from tag
id: version
run: |
if [[ ${{ github.ref }} == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
VERSION=${VERSION#v}
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "tag_with_v=v${VERSION}" >> $GITHUB_OUTPUT
else
echo "version=dev-${{ github.sha }}" >> $GITHUB_OUTPUT
echo "tag_with_v=dev" >> $GITHUB_OUTPUT
fi
Comment on lines +37 to +46
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Quote the expression to prevent potential shell injection.

${{ github.ref }} is interpolated directly into the shell script. While tag refs are unlikely to contain malicious characters, it's best practice to quote all GitHub Actions expressions to prevent injection.

Proposed fix
-        if [[ ${{ github.ref }} == refs/tags/* ]]; then
+        if [[ "${{ github.ref }}" == refs/tags/* ]]; then
🤖 Prompt for AI Agents
In @.github/workflows/publish.yml around lines 37 - 46, The shell uses unquoted
GitHub Actions expressions which can lead to injection; wrap the interpolations
in double quotes. Update the if condition to quote ${{ github.ref }} (use "${{
github.ref }}"), and quote expansions/assignments such as
VERSION="${GITHUB_REF#refs/tags/}" and any uses of ${VERSION} when echoing to
GITHUB_OUTPUT; keep references to symbols github.ref, GITHUB_REF, VERSION, and
GITHUB_OUTPUT so you change the comparison and assignment sites accordingly.


- name: Setup .NET Core
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v5.1.0
with:
dotnet-version: 9.0.x

- name: Get Engine Tag
run: |
cd RobustToolbox
git fetch --depth=1

# --- Packaging
- name: Install dependencies
run: dotnet restore

- name: Build Packaging
run: dotnet build Content.Packaging --configuration Release --no-restore /m

- name: Package server
run: dotnet run --project Content.Packaging server --platform win-x64 --platform linux-x64 --platform osx-x64 --platform linux-arm64

- name: Package client
run: dotnet run --project Content.Packaging client --no-wipe-release

- name: Publish version
run: Tools/publish_multi_request.py
env:
PUBLISH_TOKEN: ${{ secrets.PUBLISH_TOKEN }}
GITHUB_REPOSITORY: ${{ vars.GITHUB_REPOSITORY }}

- name: Publish changelog (Discord)
run: Tools/actions_changelogs_since_last_run.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DISCORD_WEBHOOK_URL: ${{ secrets.CHANGELOG_DISCORD_WEBHOOK }}

#- name: Publish changelog (RSS)
# run: Tools/actions_changelog_rss.py
# env:
# CHANGELOG_RSS_KEY: ${{ secrets.CHANGELOG_RSS_KEY }}
run: dotnet run --project Content.Packaging server --platform linux-x64 --hybrid-acz
# ---

# --- Dockerized
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=semver,pattern={{version}},value=${{ steps.version.outputs.version }}
type=semver,pattern={{major}}.{{minor}},value=${{ steps.version.outputs.version }}
type=semver,pattern={{major}},value=${{ steps.version.outputs.version }}
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Docker image
id: build
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ steps.version.outputs.version }}
BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
VCS_REF=${{ github.sha }}
Comment on lines +103 to +106
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

BUILD_DATE build-arg passes a literal string, not the evaluated date.

In docker/build-push-action, the build-args input is not processed through a shell. The value $(date -u +'%Y-%m-%dT%H:%M:%SZ') will be passed as-is to Docker, so BUILD_DATE in the image label will be the literal string $(date -u +'%Y-%m-%dT%H:%M:%SZ') rather than an actual timestamp.

Compute the date in a prior step or use a GitHub Actions expression.

Proposed fix: compute the date in a prior step

Add a step before the Docker build:

    - name: Get build date
      id: date
      run: echo "build_date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT

Then reference it in build-args:

        build-args: |
          VERSION=${{ steps.version.outputs.version }}
-          BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
+          BUILD_DATE=${{ steps.date.outputs.build_date }}
          VCS_REF=${{ github.sha }}
🤖 Prompt for AI Agents
In @.github/workflows/publish.yml around lines 103 - 106, The BUILD_DATE
build-arg is being passed as a literal shell expression; add a prior step that
computes the timestamp and exposes it as an output (e.g., a step with id "date"
that writes build_date to $GITHUB_OUTPUT), then use that output in the
docker/build-push-action build-args (replace the literal $(date ...) with ${{
steps.date.outputs.build_date }}), keeping the existing VERSION and VCS_REF
references unchanged.


- name: Create Release (only on tag)
if: startsWith(github.ref, 'refs/tags/')
uses: ncipollo/release-action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
name: Release ${{ steps.version.outputs.tag_with_v }}
body: |
Docker image: `${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}`
SHA: `${{ github.sha }}`
draft: false
prerelease: false
# ---
42 changes: 42 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# syntax=docker/dockerfile:1

FROM debian:trixie-slim AS build
WORKDIR /src

ARG VERSION=dev
ARG BUILD_DATE
ARG VCS_REF

RUN apt-get update && apt-get install -y --no-install-recommends \
unzip \
ca-certificates \
curl \
&& rm -rf /var/lib/apt/lists/*


COPY release/SS14.Server_linux-x64.zip /tmp/server.zip
RUN unzip /tmp/server.zip -d server/ \
&& rm /tmp/server.zip

RUN chmod +x /src/server/Robust.Server


FROM mcr.microsoft.com/dotnet/runtime:9.0 AS final
WORKDIR /app

ARG VERSION=dev
ARG BUILD_DATE
ARG VCS_REF

LABEL org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.created="${BUILD_DATE}" \
org.opencontainers.image.revision="${VCS_REF}" \
org.opencontainers.image.title="Exodus Monolith Server" \
org.opencontainers.image.description="SS14 Exodus Monolith Server"

COPY --from=build /src/server/ .

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:1212/status || exit 1
Comment on lines +39 to +40
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

curl is not installed in the final stage — HEALTHCHECK will always fail.

The HEALTHCHECK uses curl, but curl was only installed in the build stage (debian). The final stage (mcr.microsoft.com/dotnet/runtime:9.0) is a minimal image that does not include curl. Every health check invocation will fail with "command not found," causing Docker/orchestrators to perpetually mark the container as unhealthy.

Either install curl in the final stage, or use a tool already available (e.g., a dotnet-based check or wget if present).

Option A: Install curl in the final stage
 FROM mcr.microsoft.com/dotnet/runtime:9.0 AS final
 WORKDIR /app
 
+RUN apt-get update && apt-get install -y --no-install-recommends curl \
+    && rm -rf /var/lib/apt/lists/*
+
 ARG VERSION=dev
Option B: Remove the HEALTHCHECK from the Dockerfile and define it in docker-compose or the orchestrator instead
-HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
-    CMD curl -f http://localhost:1212/status || exit 1
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:1212/status || exit 1
🤖 Prompt for AI Agents
In `@Dockerfile` around lines 39 - 40, The HEALTHCHECK uses curl but the final
image (FROM mcr.microsoft.com/dotnet/runtime:9.0) is minimal and doesn't include
curl, so every check will fail; either install curl in the final stage by adding
package installation steps in the final stage Dockerfile (apt-get update &&
apt-get install -y curl and cleanup) or replace the HEALTHCHECK command with a
tool present in the final image (e.g., a dotnet-based probe or wget if
available), or remove the HEALTHCHECK and move it to
docker-compose/orchestrator; update the HEALTHCHECK line (the CMD that calls
curl -f http://localhost:1212/status || exit 1) accordingly to match the chosen
approach.


ENTRYPOINT [ "./Robust.Server" ]
Comment on lines +24 to +42
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Container runs as root — add a non-root USER.

Trivy flagged DS-0002: the image runs everything as root. If the server is compromised, the attacker has full root privileges inside the container. Add a dedicated user for the runtime stage.

Proposed fix
 FROM mcr.microsoft.com/dotnet/runtime:9.0 AS final
 WORKDIR /app
 
+RUN groupadd -r ss14 && useradd -r -g ss14 -d /app ss14
+
 ARG VERSION=dev
 ARG BUILD_DATE
 ARG VCS_REF
 
 LABEL org.opencontainers.image.version="${VERSION}" \
       org.opencontainers.image.created="${BUILD_DATE}" \
       org.opencontainers.image.revision="${VCS_REF}" \
       org.opencontainers.image.title="Exodus Monolith Server" \
       org.opencontainers.image.description="SS14 Exodus Monolith Server"
 
 COPY --from=build /src/server/ .
+RUN chown -R ss14:ss14 /app
+USER ss14
 
 HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
     CMD curl -f http://localhost:1212/status || exit 1
 
 ENTRYPOINT [ "./Robust.Server" ]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FROM mcr.microsoft.com/dotnet/runtime:9.0 AS final
WORKDIR /app
ARG VERSION=dev
ARG BUILD_DATE
ARG VCS_REF
LABEL org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.created="${BUILD_DATE}" \
org.opencontainers.image.revision="${VCS_REF}" \
org.opencontainers.image.title="Exodus Monolith Server" \
org.opencontainers.image.description="SS14 Exodus Monolith Server"
COPY --from=build /src/server/ .
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:1212/status || exit 1
ENTRYPOINT [ "./Robust.Server" ]
FROM mcr.microsoft.com/dotnet/runtime:9.0 AS final
WORKDIR /app
RUN groupadd -r ss14 && useradd -r -g ss14 -d /app ss14
ARG VERSION=dev
ARG BUILD_DATE
ARG VCS_REF
LABEL org.opencontainers.image.version="${VERSION}" \
org.opencontainers.image.created="${BUILD_DATE}" \
org.opencontainers.image.revision="${VCS_REF}" \
org.opencontainers.image.title="Exodus Monolith Server" \
org.opencontainers.image.description="SS14 Exodus Monolith Server"
COPY --from=build /src/server/ .
RUN chown -R ss14:ss14 /app
USER ss14
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:1212/status || exit 1
ENTRYPOINT [ "./Robust.Server" ]
🤖 Prompt for AI Agents
In `@Dockerfile` around lines 24 - 42, Add a non-root runtime user for the final
stage: create a dedicated user/group (e.g., "exodus") in the final stage (the
stage using mcr.microsoft.com/dotnet/runtime:9.0), chown the application
directory (/app) so that the new user owns the files copied by COPY --from=build
/src/server/ ., and add a USER instruction before ENTRYPOINT to run
Robust.Server as that non-root user; ensure any required runtime permissions are
granted to that user so the HEALTHCHECK and server can run.

Loading