Fixed the CAP_NET_RAW capabilities were not inherited. #936
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| name: Unit-test | |
| on: # yamllint disable-line rule:truthy | |
| pull_request: | |
| workflow_call: | |
| concurrency: | |
| group: '${{ github.workflow }} @ ${{ github.ref }}' | |
| cancel-in-progress: true | |
| jobs: | |
| unit-test-amd64-steamcmd: | |
| name: Docker - Test (amd64-steamcmd) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| - name: Test negative delta recovery setting | |
| run: ./tests/test-negative-delta-recovery.sh | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Build and export to Docker | |
| uses: docker/build-push-action@v7 | |
| with: | |
| file: ./Dockerfile | |
| load: true | |
| tags: ${{ github.run_id }} | |
| platforms: linux/amd64 | |
| - name: Reject invalid negative delta recovery setting | |
| run: | | |
| set +e | |
| output="$(timeout --signal=TERM --kill-after=5s 30s docker run --rm \ | |
| --name palworld-server-invalid-${{ github.run_id }} \ | |
| --env-file .env.example \ | |
| -e PALWORLD_ALLOW_NEGATIVE_DELTA_TIME=invalid \ | |
| ${{ github.run_id }} 2>&1)" | |
| status=$? | |
| set -e | |
| docker rm -f palworld-server-invalid-${{ github.run_id }} >/dev/null 2>&1 || true | |
| if [ "${status}" -ne 1 ]; then | |
| echo "Expected exit code 1 for invalid setting, got ${status}." | |
| exit 1 | |
| fi | |
| if ! grep -Fq \ | |
| "PALWORLD_ALLOW_NEGATIVE_DELTA_TIME must be true or false." \ | |
| <<< "${output}"; then | |
| echo "Expected invalid-setting error was not logged." | |
| exit 1 | |
| fi | |
| - name: Reject empty negative delta recovery setting | |
| run: | | |
| set +e | |
| output="$(timeout --signal=TERM --kill-after=5s 30s docker run --rm \ | |
| --name palworld-server-empty-${{ github.run_id }} \ | |
| --env-file .env.example \ | |
| -e PALWORLD_ALLOW_NEGATIVE_DELTA_TIME= \ | |
| ${{ github.run_id }} 2>&1)" | |
| status=$? | |
| set -e | |
| docker rm -f palworld-server-empty-${{ github.run_id }} >/dev/null 2>&1 || true | |
| if [ "${status}" -ne 1 ]; then | |
| echo "Expected exit code 1 for empty setting, got ${status}." | |
| exit 1 | |
| fi | |
| if ! grep -Fq \ | |
| "PALWORLD_ALLOW_NEGATIVE_DELTA_TIME must be true or false." \ | |
| <<< "${output}"; then | |
| echo "Expected empty-setting error was not logged." | |
| exit 1 | |
| fi | |
| - name: Run server | |
| run: | | |
| docker run -d \ | |
| --name palworld-server \ | |
| -p 8211:8211/udp \ | |
| -p 27015:27015/udp \ | |
| -p 25575:25575/tcp \ | |
| -v ./palworld:/palworld/ \ | |
| --env-file .env.example \ | |
| --restart unless-stopped \ | |
| --stop-timeout 30 \ | |
| ${{ github.run_id }} | |
| - name: Wait for server to start | |
| run: | | |
| TIMEOUT_SECONDS=240 | |
| START_TIME=$(date +%s) | |
| while ! docker logs palworld-server 2>&1 | grep -q "Setting breakpad minidump AppID"; do | |
| CURRENT_TIME=$(date +%s) | |
| ELAPSED_TIME=$((CURRENT_TIME - START_TIME)) | |
| if [ $ELAPSED_TIME -gt $TIMEOUT_SECONDS ]; then | |
| echo "Timeout reached. Server failed to start within $TIMEOUT_SECONDS seconds." | |
| printf "\e[0;32m%s\e[0m\n" "*****Container LOGS*****" | |
| docker logs palworld-server | |
| exit 1 | |
| fi | |
| echo "Waiting for server to start..." | |
| sleep 5 | |
| done | |
| - name: Test negative delta recovery is disabled by default | |
| run: | | |
| docker exec palworld-server bash -c ' | |
| pal_pid="$(pidof PalServer-Linux-Shipping)" | |
| pal_pid="${pal_pid%% *}" | |
| if [ -z "${pal_pid}" ]; then | |
| echo "PalServer process is missing." | |
| exit 1 | |
| fi | |
| mapfile -d "" -t arguments < "/proc/${pal_pid}/cmdline" | |
| for argument in "${arguments[@]}"; do | |
| if [ "${argument}" = "-ini:Engine:[ConsoleVariables]:Pal.AllowNegativeDeltaTime=1" ]; then | |
| echo "Negative delta recovery was unexpectedly enabled." | |
| exit 1 | |
| fi | |
| done | |
| ' | |
| # - name: Test if rcon.yaml is valid | |
| # run: | | |
| # printf "\e[0;32m%s\e[0m\n" "*****RCON.YAML*****" | |
| # docker exec palworld-server cat /home/steam/server/rcon.yaml | |
| # RCON_PORT=$(docker exec palworld-server env | grep RCON_PORT | cut -d'=' -f2) | |
| # ADMIN_PASSWORD=$(docker exec palworld-server env | grep ADMIN_PASSWORD | cut -d'=' -f2) | |
| # YAML_PORT=$(docker exec palworld-server cat /home/steam/server/rcon.yaml | grep "^ address:" | awk '{print $2}' | cut -d ':' -f2 | tr -d '"') | |
| # YAML_PASSWORD=$(docker exec palworld-server cat /home/steam/server/rcon.yaml | grep "^ password:" | awk '{print $2}' | tr -d '"') | |
| # if [ ! $RCON_PORT == $YAML_PORT ]; then | |
| # echo "Error: $RCON_PORT in .env.example does not match $YAML_PORT in rcon.yaml." | |
| # exit 2 | |
| # fi | |
| # if [ ! "$ADMIN_PASSWORD" == "$YAML_PASSWORD" ]; then | |
| # echo "Error: $ADMIN_PASSWORD in .env.example does not match $YAML_PASSWORD in rcon.yaml." | |
| # exit 3 | |
| # fi | |
| # - name: Test if rcon works | |
| # run: | | |
| # sleep 5 | |
| # if ! docker exec palworld-server rcon-cli Info | grep -q "Welcome to Pal Server"; then | |
| # echo "Server may not have started successfully." | |
| # exit 4 | |
| # fi | |
| # OUTPUT=$(docker exec palworld-server rcon-cli "Broadcast test" 2>&1) | |
| # if [[ $OUTPUT != *"Broadcasted: test"* ]]; then | |
| # echo "Error: Unexpected output - $OUTPUT" | |
| # exit 5 | |
| # fi | |
| # OUTPUT=$(docker exec palworld-server rcon-cli save 2>&1) | |
| # if [[ $OUTPUT != *"Complete Save"* ]]; then | |
| # echo "Error: Unexpected output - $OUTPUT" | |
| # exit 6 | |
| # fi | |
| - name: Test if the REST API works | |
| run: | | |
| sleep 100 | |
| if ! docker exec palworld-server rest-cli info | grep -q "\"version\"\:"; then | |
| echo "Server may not have started successfully." | |
| exit 4 | |
| fi | |
| docker exec palworld-server rest-cli announce "Hello, Palworld!" | |
| if docker logs palworld-server 2>&1 | grep -q "REST accessed endpoint /v1/api/announce OK"; then | |
| echo "Announce OK — continuing." | |
| else | |
| echo "Required log entry not found — exiting with code 5." | |
| exit 5 | |
| fi | |
| docker exec palworld-server rest-cli save | |
| if docker logs palworld-server 2>&1 | grep -q "REST accessed endpoint /v1/api/save OK"; then | |
| echo "Save OK — continuing." | |
| else | |
| echo "Required log entry not found — exiting with code 5." | |
| exit 5 | |
| fi | |
| - name: Test if port 8211, 27015, 25575 and 8212 are listening | |
| run: | | |
| nc -z -u -v 127.0.0.1 8211 || exit 7 | |
| nc -z -u -v 127.0.0.1 27015 || exit 8 | |
| nc -z -v 127.0.0.1 25575 || exit 9 | |
| - name: Test the backup script | |
| run: | | |
| docker exec palworld-server backup | |
| if [ ! -f ./palworld/backups/palworld-save-*.tar.gz ]; then | |
| echo "Backup file not found. Backup command may have failed." | |
| exit 10 | |
| fi | |
| - name: Test if PalWorldSettings.ini is valid | |
| run: | | |
| if [ ! -f ./palworld/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini ]; then | |
| echo "Error: PalWorldSettings.ini file is missing." | |
| exit 11 | |
| fi | |
| if ! grep -q "\[\/Script\/Pal.PalGameWorldSettings\]" ./palworld/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini; then | |
| echo "Error: PalWorldSettings.ini is missing the required section [/Script/Pal.PalGameWorldSettings]." | |
| exit 12 | |
| fi | |
| if ! grep -q "^OptionSettings=\(.*\)" ./palworld/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini; then | |
| echo "Error: PalWorldSettings.ini is missing or has an invalid OptionSettings section." | |
| exit 13 | |
| fi | |
| # unit-test-amd64-depotdownloader: | |
| # name: Docker - Test (amd64-depotdownloader) | |
| # runs-on: ubuntu-latest | |
| # steps: | |
| # - name: Checkout | |
| # uses: actions/checkout@v7 | |
| # - name: Set up Docker Buildx | |
| # uses: docker/setup-buildx-action@v4 | |
| # - name: Build and export to Docker | |
| # uses: docker/build-push-action@v7 | |
| # with: | |
| # file: ./Dockerfile | |
| # load: true | |
| # tags: ${{ github.run_id }} | |
| # platforms: linux/amd64 | |
| # - name: Run server | |
| # run: | | |
| # sed -i 's/^USE_DEPOT_DOWNLOADER=False/USE_DEPOT_DOWNLOADER=True/' .env.example && \ | |
| # docker run -d \ | |
| # --name palworld-server \ | |
| # -p 8211:8211/udp \ | |
| # -p 27015:27015/udp \ | |
| # -p 25575:25575/tcp \ | |
| # -v ./palworld:/palworld/ \ | |
| # --env-file .env.example \ | |
| # --restart unless-stopped \ | |
| # --stop-timeout 30 \ | |
| # ${{ github.run_id }} | |
| # - name: Wait for server to start | |
| # run: | | |
| # TIMEOUT_SECONDS=180 | |
| # START_TIME=$(date +%s) | |
| # while ! docker logs palworld-server 2>&1 | grep -q "Setting breakpad minidump AppID"; do | |
| # CURRENT_TIME=$(date +%s) | |
| # ELAPSED_TIME=$((CURRENT_TIME - START_TIME)) | |
| # if [ $ELAPSED_TIME -gt $TIMEOUT_SECONDS ]; then | |
| # echo "Timeout reached. Server failed to start within $TIMEOUT_SECONDS seconds." | |
| # printf "\e[0;32m%s\e[0m\n" "*****Container LOGS*****" | |
| # docker logs palworld-server | |
| # exit 1 | |
| # fi | |
| # echo "Waiting for server to start..." | |
| # sleep 5 | |
| # done | |
| # # - name: Test if rcon.yaml is valid | |
| # # run: | | |
| # # printf "\e[0;32m%s\e[0m\n" "*****RCON.YAML*****" | |
| # # docker exec palworld-server cat /home/steam/server/rcon.yaml | |
| # # RCON_PORT=$(docker exec palworld-server env | grep RCON_PORT | cut -d'=' -f2) | |
| # # ADMIN_PASSWORD=$(docker exec palworld-server env | grep ADMIN_PASSWORD | cut -d'=' -f2) | |
| # # YAML_PORT=$(docker exec palworld-server cat /home/steam/server/rcon.yaml | grep "^ address:" | awk '{print $2}' | cut -d ':' -f2 | tr -d '"') | |
| # # YAML_PASSWORD=$(docker exec palworld-server cat /home/steam/server/rcon.yaml | grep "^ password:" | awk '{print $2}' | tr -d '"') | |
| # # if [ ! $RCON_PORT == $YAML_PORT ]; then | |
| # # echo "Error: $RCON_PORT in .env.example does not match $YAML_PORT in rcon.yaml." | |
| # # exit 2 | |
| # # fi | |
| # # if [ ! "$ADMIN_PASSWORD" == "$YAML_PASSWORD" ]; then | |
| # # echo "Error: $ADMIN_PASSWORD in .env.example does not match $YAML_PASSWORD in rcon.yaml." | |
| # # exit 3 | |
| # # fi | |
| # # - name: Test if rcon works | |
| # # run: | | |
| # # sleep 5 | |
| # # if ! docker exec palworld-server rcon-cli Info | grep -q "Welcome to Pal Server"; then | |
| # # echo "Server may not have started successfully." | |
| # # exit 4 | |
| # # fi | |
| # # OUTPUT=$(docker exec palworld-server rcon-cli "Broadcast test" 2>&1) | |
| # # if [[ $OUTPUT != *"Broadcasted: test"* ]]; then | |
| # # echo "Error: Unexpected output - $OUTPUT" | |
| # # exit 5 | |
| # # fi | |
| # # OUTPUT=$(docker exec palworld-server rcon-cli save 2>&1) | |
| # # if [[ $OUTPUT != *"Complete Save"* ]]; then | |
| # # echo "Error: Unexpected output - $OUTPUT" | |
| # # exit 6 | |
| # # fi | |
| # - name: Test if the REST API works | |
| # run: | | |
| # sleep 10 | |
| # if ! docker exec palworld-server rest-cli info | grep -q "\"version\"\:"; then | |
| # echo "Server may not have started successfully." | |
| # exit 4 | |
| # fi | |
| # docker exec palworld-server rest-cli announce "Hello, Palworld!" | |
| # if docker logs palworld-server 2>&1 | grep -q "REST accessed endpoint /v1/api/announce OK"; then | |
| # echo "Announce OK — continuing." | |
| # else | |
| # echo "Required log entry not found — exiting with code 5." | |
| # exit 5 | |
| # fi | |
| # docker exec palworld-server rest-cli save | |
| # if docker logs palworld-server 2>&1 | grep -q "REST accessed endpoint /v1/api/save OK"; then | |
| # echo "Save OK — continuing." | |
| # else | |
| # echo "Required log entry not found — exiting with code 5." | |
| # exit 5 | |
| # fi | |
| # - name: Test if port 8211, 27015, 25575 and 8212 are listening | |
| # run: | | |
| # nc -z -u -v 127.0.0.1 8211 || exit 7 | |
| # nc -z -u -v 127.0.0.1 27015 || exit 8 | |
| # nc -z -v 127.0.0.1 25575 || exit 9 | |
| # - name: Test the backup script | |
| # run: | | |
| # docker exec palworld-server backup | |
| # if [ ! -f ./palworld/backups/palworld-save-*.tar.gz ]; then | |
| # echo "Backup file not found. Backup command may have failed." | |
| # exit 10 | |
| # fi | |
| # - name: Test if PalWorldSettings.ini is valid | |
| # run: | | |
| # if [ ! -f ./palworld/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini ]; then | |
| # echo "Error: PalWorldSettings.ini file is missing." | |
| # exit 11 | |
| # fi | |
| # if ! grep -q "\[\/Script\/Pal.PalGameWorldSettings\]" ./palworld/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini; then | |
| # echo "Error: PalWorldSettings.ini is missing the required section [/Script/Pal.PalGameWorldSettings]." | |
| # exit 12 | |
| # fi | |
| # if ! grep -q "^OptionSettings=\(.*\)" ./palworld/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini; then | |
| # echo "Error: PalWorldSettings.ini is missing or has an invalid OptionSettings section." | |
| # exit 13 | |
| # fi | |
| unit-test-arm64: | |
| name: Docker - Test (arm64) | |
| runs-on: [self-hosted, ARM64] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| # - name: Set up QEMU | |
| # uses: docker/setup-qemu-action@v3 | |
| # with: | |
| # image: tonistiigi/binfmt:qemu-v8.1.5 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Build and export to Docker | |
| uses: docker/build-push-action@v7 | |
| with: | |
| file: ./Dockerfile | |
| load: true | |
| tags: ${{ github.run_id }}:arm64 | |
| platforms: linux/arm64 | |
| - name: Run server | |
| run: | | |
| sed -i 's/^USE_DEPOT_DOWNLOADER=False/USE_DEPOT_DOWNLOADER=true/' .env.example && \ | |
| docker run -d \ | |
| --name palworld-server-${{ github.run_id }} \ | |
| --platform linux/arm64 \ | |
| -p 8211:8211/udp \ | |
| -p 27015:27015/udp \ | |
| -p 25575:25575/tcp \ | |
| -v ./palworld-${{ github.run_id }}:/palworld/ \ | |
| --env-file .env.example \ | |
| -e PALWORLD_ALLOW_NEGATIVE_DELTA_TIME=true \ | |
| --restart unless-stopped \ | |
| --stop-timeout 30 \ | |
| ${{ github.run_id }}:arm64 | |
| - name: Wait for server to start | |
| run: | | |
| TIMEOUT_SECONDS=660 | |
| START_TIME=$(date +%s) | |
| while ! docker logs palworld-server-${{ github.run_id }} 2>&1 | grep -q "Setting breakpad minidump AppID"; do | |
| CURRENT_TIME=$(date +%s) | |
| ELAPSED_TIME=$((CURRENT_TIME - START_TIME)) | |
| if [ $ELAPSED_TIME -gt $TIMEOUT_SECONDS ]; then | |
| echo "Timeout reached. Server failed to start within $TIMEOUT_SECONDS seconds." | |
| printf "\e[0;32m%s\e[0m\n" "*****Container LOGS*****" | |
| docker logs palworld-server-${{ github.run_id }} | |
| exit 1 | |
| fi | |
| echo "Waiting for server to start..." | |
| sleep 5 | |
| done | |
| - name: Test negative delta recovery process argument | |
| run: | | |
| docker exec palworld-server-${{ github.run_id }} bash -c ' | |
| pal_pid="$(pidof PalServer-Linux-Shipping)" | |
| pal_pid="${pal_pid%% *}" | |
| if [ -z "${pal_pid}" ]; then | |
| echo "PalServer process is missing." | |
| exit 1 | |
| fi | |
| mapfile -d "" -t arguments < "/proc/${pal_pid}/cmdline" | |
| count=0 | |
| for argument in "${arguments[@]}"; do | |
| if [ "${argument}" = "-ini:Engine:[ConsoleVariables]:Pal.AllowNegativeDeltaTime=1" ]; then | |
| count=$((count + 1)) | |
| fi | |
| done | |
| if [ "${count}" -ne 1 ]; then | |
| echo "Expected exactly one negative delta recovery process argument." | |
| exit 1 | |
| fi | |
| ' | |
| # RCON is deprecated, so skipping this test for now | |
| # - name: Test if rcon.yaml is valid | |
| # run: | | |
| # printf "\e[0;32m%s\e[0m\n" "*****RCON.YAML*****" | |
| # docker exec palworld-server-${{ github.run_id }} cat /home/steam/server/rcon.yaml | |
| # RCON_PORT=$(docker exec palworld-server-${{ github.run_id }} env | grep RCON_PORT | cut -d'=' -f2) | |
| # ADMIN_PASSWORD=$(docker exec palworld-server-${{ github.run_id }} env | grep ADMIN_PASSWORD | cut -d'=' -f2) | |
| # YAML_PORT=$(docker exec palworld-server-${{ github.run_id }} cat /home/steam/server/rcon.yaml | grep "^ address:" | awk '{print $2}' | cut -d ':' -f2 | tr -d '"') | |
| # YAML_PASSWORD=$(docker exec palworld-server-${{ github.run_id }} cat /home/steam/server/rcon.yaml | grep "^ password:" | awk '{print $2}' | tr -d '"') | |
| # if [ ! $RCON_PORT == $YAML_PORT ]; then | |
| # echo "Error: $RCON_PORT in .env.example does not match $YAML_PORT in rcon.yaml." | |
| # exit 2 | |
| # fi | |
| # if [ ! "$ADMIN_PASSWORD" == "$YAML_PASSWORD" ]; then | |
| # echo "Error: $ADMIN_PASSWORD in .env.example does not match $YAML_PASSWORD in rcon.yaml." | |
| # exit 3 | |
| # fi | |
| # - name: Test if rcon works | |
| # run: | | |
| # sleep 100 | |
| # if ! docker exec palworld-server-${{ github.run_id }} rcon-cli Info | grep -q "Welcome to Pal Server"; then | |
| # echo "Server may not have started successfully." | |
| # exit 4 | |
| # fi | |
| # OUTPUT=$(docker exec palworld-server-${{ github.run_id }} rcon-cli "Broadcast test" 2>&1) | |
| # if [[ $OUTPUT != *"Broadcasted: test"* ]]; then | |
| # echo "Error: Unexpected output - $OUTPUT" | |
| # exit 5 | |
| # fi | |
| # OUTPUT=$(docker exec palworld-server-${{ github.run_id }} rcon-cli save 2>&1) | |
| # if [[ $OUTPUT != *"Complete Save"* ]]; then | |
| # echo "Error: Unexpected output - $OUTPUT" | |
| # exit 6 | |
| # fi | |
| - name: Test if the REST API works | |
| run: | | |
| sleep 180 | |
| if ! docker exec palworld-server-${{ github.run_id }} rest-cli info | grep -q "\"version\"\:"; then | |
| echo "Server may not have started successfully." | |
| exit 4 | |
| fi | |
| docker exec palworld-server-${{ github.run_id }} rest-cli announce "Hello, Palworld!" | |
| if docker logs palworld-server-${{ github.run_id }} 2>&1 | grep -q "REST accessed endpoint /v1/api/announce OK"; then | |
| echo "Announce OK — continuing." | |
| else | |
| echo "Required log entry not found — exiting with code 5." | |
| exit 5 | |
| fi | |
| docker exec palworld-server-${{ github.run_id }} rest-cli save | |
| if docker logs palworld-server-${{ github.run_id }} 2>&1 | grep -q "REST accessed endpoint /v1/api/save OK"; then | |
| echo "Save OK — continuing." | |
| else | |
| echo "Required log entry not found — exiting with code 5." | |
| exit 5 | |
| fi | |
| - name: Test if port 8211, 27015, 25575 and 8212 are listening | |
| run: | | |
| nc -z -u -v 127.0.0.1 8211 || exit 7 | |
| nc -z -u -v 127.0.0.1 27015 || exit 8 | |
| nc -z -v 127.0.0.1 25575 || exit 9 | |
| - name: Test the backup script | |
| run: | | |
| docker exec palworld-server-${{ github.run_id }} backup | |
| if [ ! -f ./palworld-${{ github.run_id }}/backups/palworld-save-*.tar.gz ]; then | |
| echo "Backup file not found. Backup command may have failed." | |
| exit 10 | |
| fi | |
| - name: Test if PalWorldSettings.ini is valid | |
| run: | | |
| if [ ! -f ./palworld-${{ github.run_id }}/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini ]; then | |
| echo "Error: PalWorldSettings.ini file is missing." | |
| exit 11 | |
| fi | |
| if ! grep -q "\[\/Script\/Pal.PalGameWorldSettings\]" ./palworld-${{ github.run_id }}/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini; then | |
| echo "Error: PalWorldSettings.ini is missing the required section [/Script/Pal.PalGameWorldSettings]." | |
| exit 12 | |
| fi | |
| if ! grep -q "^OptionSettings=\(.*\)" ./palworld-${{ github.run_id }}/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini; then | |
| echo "Error: PalWorldSettings.ini is missing or has an invalid OptionSettings section." | |
| exit 13 | |
| fi | |
| - name: Stop server | |
| if: always() | |
| run: | | |
| docker stop palworld-server-${{ github.run_id }} | |
| docker rm palworld-server-${{ github.run_id }} |