Skip to content
Merged
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
4 changes: 2 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
# - pip (pixi shadow) : pixi.toml dependencies are resolved via conda-forge
# and are not tracked here; see SECURITY.md / docs/DEPENDENCY_AUDIT.md.
#
# The bundled C/C++ libraries live in the libs/ git submodule (separate repo).
# submodule and are version-bumped there, not in this repo.
# The bundled C/C++ libraries live in the libs/ git submodule (separate repo)
# and are version-bumped there, not in this repo.

version: 2
updates:
Expand Down
21 changes: 16 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ jobs:
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
with:
distribution: "temurin"
java-version: "17"
java-version: "21"
cache: "gradle"
cache-dependency-path: |
**/*.gradle*
Expand Down Expand Up @@ -358,7 +358,17 @@ jobs:
# This step also generates the final packages for 32 bit lnx.
mod-merger:
runs-on: ubuntu-24.04
needs: [ pre-build, lnx64-mod, lnx32-mod, osx-mod, win-mod, win64-mod, lnx-aarch64-mod, android-mod ]
needs:
[
pre-build,
lnx64-mod,
lnx32-mod,
osx-mod,
win-mod,
win64-mod,
lnx-aarch64-mod,
android-mod,
]
steps:
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
Expand Down Expand Up @@ -416,7 +426,7 @@ jobs:
# Generate the final packages for Lnx, macOS, Windows and Android
lnx64:
runs-on: ubuntu-24.04
needs: [ pre-build, mod-merger ]
needs: [pre-build, mod-merger]
env:
CI_ETL_DESCRIBE: ${{needs.pre-build.outputs.describe}}
CI_ETL_TAG: ${{needs.pre-build.outputs.tag}}
Expand Down Expand Up @@ -765,7 +775,7 @@ jobs:
CI_ETL_UID: ${{needs.pre-build.outputs.uid}}
ANDROID_SDK_ROOT: /opt/android-sdk
GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.workers.max=4 -Dkotlin.incremental=false
needs: [ pre-build, mod-merger ]
needs: [pre-build, mod-merger]
container:
image: etlegacy/android-build
steps:
Expand All @@ -779,7 +789,7 @@ jobs:
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
with:
distribution: "temurin"
java-version: "17"
java-version: "21"
cache: "gradle"
cache-dependency-path: |
**/*.gradle*
Expand Down Expand Up @@ -816,6 +826,7 @@ jobs:
ls -R

- name: Rename APK
shell: bash
run: |
shopt -s nullglob globstar
for FILE in ./app/build/outputs/apk/**/*.apk; do mv "$FILE" "${FILE%-*}.apk"; done
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ jobs:
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
with:
distribution: "temurin"
java-version: "17"
# JDK 21+: Gradle 8.x must instrument deps with Java 21 bytecode (e.g. BouncyCastle 1.79)
java-version: "21"
cache: "gradle"
cache-dependency-path: |
**/*.gradle*
Expand All @@ -292,6 +293,7 @@ jobs:
ls -R

- name: Rename APK
shell: bash
run: |
shopt -s nullglob
for FILE in ./app/build/outputs/apk/debug/*.apk; do mv "$FILE" "${FILE%-*}.apk"; done
Expand Down Expand Up @@ -354,6 +356,11 @@ jobs:
RUN_ID: ${{ github.run_id }}
DEVS_ROLE_ID: "260752921698762752"
run: |
if [ -z "${DISCORD_WEBHOOK:-}" ]; then
echo "DISCORD_WEBHOOK unset; skipping Discord notification."
exit 0
fi

RUN_URL="https://github.com/${REPO}/actions/runs/${RUN_ID}"

MESSAGE="❌ **[failed on commit](<${RUN_URL}>)** \`${COMMIT_SHA}\` <@&${DEVS_ROLE_ID}>"
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ app/.cxx
app/build/
build/
gradle/
# Vendored JoyStick library ships its own Gradle wrapper; root `gradle/` would hide it
!/app/libs/joystick/gradle/
!/app/libs/joystick/gradle/wrapper/
!/app/libs/joystick/gradle/wrapper/gradle-wrapper.properties
/local.properties

# Package Managers
Expand Down
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER ${CMAKE_TARGETS_FOLDER})

# Set language levels (C++17: constexpr-if, nested namespace, structured bindings;
# still avoids C++20 modules/concepts for older toolchains in long-tail CI images)
# still avoids C++20 modules/concepts for older toolchains in long-tail CI images).
# The qagame Omni-bot bridge is pinned to C++11 in cmake/ETLBuildMod.cmake so
# etlegacy/lnx-build CI images can still configure when FEATURE_OMNIBOT is on.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
Expand Down
4 changes: 3 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pixi run upstream-fetch

Formatting and workflow checks used in CI can be run locally with `pixi install` and `pixi run -e validation check-changes`. The default comparison branch is read from `.upstream-remote-branch` when that file exists (for example `origin/main` on forks that use `main` as the default branch).

Continuous integration is documented briefly in **[README.md](README.md)** under **CI and workflows** (main workflow, ETLBuild, Snap, optional Discord webhook).

Bundled native library bumps that belong in the **`libs`** submodule may be prepared as mailbox patches under **`misc/patches/`** (see `misc/patches/README.md`) when you cannot push to the **`libs`** remote directly.

## COVERITY SCAN (OPTIONAL)
Expand All @@ -64,7 +66,7 @@ Optional **variable** `COVERITY_PROJECT` (repository **Actions → Variables**)

## ANDROID JOYSTICK (VENDORED)

The on-screen joystick library is kept under **`app/libs/joystick/`** as normal project files (not a git submodule). When upgrading Android Gradle Plugin or the library itself, keep **`app/libs/joystick/build.gradle`** in step with the root **`build.gradle`** `classpath` version. Optional: compare with [etlegacy/JoyStick](https://github.com/etlegacy/JoyStick) upstream and port changes manually.
The on-screen joystick library is kept under **`app/libs/joystick/`** as normal project files (not a git submodule). **`app/libs/joystick/gradle/wrapper/`** (`gradle-wrapper.properties` and **`gradle-wrapper.jar`**) must remain committed (the repo-wide **`gradle/`** ignore rule is negated for that path so CI can run `./gradlew`). Keep the JoyStick **Gradle distribution URL** in step with the root project’s **`gradle/wrapper/gradle-wrapper.properties`** so dependency bytecode matches the wrapper’s ASM. When upgrading Android Gradle Plugin or the library itself, keep **`app/libs/joystick/build.gradle`** in step with the root **`build.gradle`** `classpath` version. Optional: compare with [etlegacy/JoyStick](https://github.com/etlegacy/JoyStick) upstream and port changes manually.

## COMMUNICATION

Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![CI](https://github.com/timfox/sturmgeist/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/timfox/sturmgeist/actions/workflows/ci.yml?query=branch%3Amain)
[![ETLBuild](https://github.com/timfox/sturmgeist/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/timfox/sturmgeist/actions/workflows/build.yml?query=branch%3Amain)
[![Snap](https://snapcraft.io/etlegacy/badge.svg)](https://snapcraft.io/etlegacy)
[![Snap](https://snapcraft.io/etlegacy/badge.svg)](https://snapcraft.io/etlegacy) (upstream package; see [Snap](#snap))
[![Coverity](https://scan.coverity.com/projects/1160/badge.svg)](https://scan.coverity.com/projects/1160)
[![Discord](https://img.shields.io/discord/260750790203932672.svg?logo=discord)](https://discord.gg/UBAZFys)

Expand Down Expand Up @@ -100,6 +100,12 @@ pixi run upstream-fetch

See [Development helpers](#development-helpers) and [CONTRIBUTING.md](CONTRIBUTING.md).

## CI and workflows

GitHub Actions on **`main`** / **`master`** run **[`.github/workflows/ci.yml`](.github/workflows/ci.yml)** (Linux containers, macOS, Windows, Android, optional log checks). The **Android** job uses **JDK 21** in CI, and the vendored **JoyStick** library uses the same **Gradle 8.13** wrapper as the root app so Gradle can instrument current dependency bytecode (for example BouncyCastle multi-release JARs). **[`build.yml`](.github/workflows/build.yml)** (ETLBuild) runs on tagged releases, a weekly schedule, and manual dispatch. **[`snapcraft.yml`](.github/workflows/snapcraft.yml)** builds the upstream **[etlegacy-snap](https://github.com/etlegacy/etlegacy-snap)** tree after ETLBuild completes; it expects **`SNAPCRAFT_STORE_CREDENTIALS`** where publishing is desired.

Forks without **`LEGACY_CI_WEBHOOK`** still get a full CI signal; the optional Discord notify step is skipped when that secret is unset. The **`check-compiler-warnings`** job scans native build logs for new compiler warnings in game code; **Android** and **Windows** (`win` / `win64`) logs are treated as informational only (see `misc/collect-and-check-gh-build-logs.py`).

## Development helpers

[Pixi](https://pixi.sh/) workspace: **`pixi.toml`**.
Expand Down Expand Up @@ -204,7 +210,7 @@ OpenGL and GLES are supported. See **`easybuild.sh`** (`RPI` section): e.g. `./e

### Snap

Snap packaging: [etlegacy-snap](https://github.com/etlegacy/etlegacy-snap).
Official ET: Legacy snap sources live in **[etlegacy/etlegacy-snap](https://github.com/etlegacy/etlegacy-snap)** ([snapcraft.io/etlegacy](https://snapcraft.io/etlegacy)). This fork’s workflow checks out that repo to build; it is not a fork-specific snap name unless you maintain your own branch and store credentials.

## License

Expand Down
11 changes: 5 additions & 6 deletions app/libs/joystick/.github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Publish package to GitHub Packages
on:
push:
tags:
- 'v*'
- "v*"
workflow_dispatch:
release:
types: [created]
Expand All @@ -22,11 +22,11 @@ jobs:
fetch-tags: true

- uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4
name: Setup Java 17
name: Setup Java 21
with:
java-version: '17'
distribution: 'temurin'
cache: 'gradle'
java-version: "21"
distribution: "temurin"
cache: "gradle"

- name: Setup Android SDK
uses: android-actions/setup-android@9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407 # v3
Expand All @@ -35,4 +35,3 @@ jobs:
run: ./gradlew publish --no-daemon --info
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Binary file modified app/libs/joystick/gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
6 changes: 6 additions & 0 deletions app/libs/joystick/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
11 changes: 11 additions & 0 deletions cmake/ETLBuildMod.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,17 @@ if(BUILD_SERVER_MOD)
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${MODNAME}"
)
target_compile_definitions(qagame PRIVATE GAMEDLL=1 MODLIB=1)

# Omni-bot adds C++ sources to qagame; etlegacy/lnx-build CI images ship an older
# g++ where CMake does not enable C++17 for this target. Pin C++11 for qagame only.
if(FEATURE_OMNIBOT)
set_target_properties(qagame
PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
)
endif()
endif()

#
Expand Down
9 changes: 5 additions & 4 deletions misc/collect-and-check-gh-build-logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import requests
import sys


EXPLICITLY_IGNORED_WARNINGS = {
"android": [],
"lnx-aarch64": [
Expand Down Expand Up @@ -142,7 +141,9 @@ def check_logs(args):
found_logs_count += 1
arch = (txt_file.split("job-logs-")[1]).split(".txt")[0]

is_non_pertinent = "android" in txt_file or "win64" in txt_file
# MSVC emits many benign C4267/C4311 warnings in legacy code; treat both
# Windows jobs like win64 (already non-pertinent upstream).
is_non_pertinent = arch in ("android", "win", "win64")
pertinent_lines, skipped_lines = clean_and_process_file(arch, txt_file)

if not args.show_skipped and len(pertinent_lines) <= 0:
Expand All @@ -152,7 +153,7 @@ def check_logs(args):
print("###", f"{arch:11} - START", f"({txt_file})", "{{{")
if is_non_pertinent:
print(
f"# INFO - {arch.capitalize()} warnings are never pertinent for now ..."
f"# INFO - {arch} job warnings are treated as non-pertinent for this check."
)
else:
failed += len(pertinent_lines)
Expand Down Expand Up @@ -182,7 +183,7 @@ def check_logs(args):
)
if failed > 0:
print(
f"{failed} pertinent warnings were emitted (ignoring Android), failing..."
f"{failed} pertinent warnings were emitted (ignoring Android and Windows jobs), failing..."
)
exit(1)
else:
Expand Down
Loading