Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
cc9fdaa
autotester: Docker-based in-game integration test framework
Skidamek May 20, 2026
eef9b63
autotester: Docker-based in-game integration test framework
Skidamek May 20, 2026
f2f2ca3
move manual docker managment to a proper python docker lib
Skidamek May 20, 2026
b93bb1f
piss
Skidamek May 20, 2026
7b8bf9d
piss
Skidamek May 20, 2026
883927d
reuse build workflow
Skidamek May 20, 2026
a0d2f04
shit
Skidamek May 20, 2026
133640e
aaaaaa
Skidamek May 21, 2026
0eeaaa6
bbb
Skidamek May 21, 2026
4d52d8a
drop problematic and not widely used 1.20.4
Skidamek May 21, 2026
367af7e
stop redownloading cached minecraft assets
Skidamek May 21, 2026
8d8d1df
run stonecutter set 26.1-fabric version
Skidamek May 22, 2026
5f4d53e
fix login packets race condition on 1.21.1+
Skidamek May 22, 2026
10a70ca
more login packets improvements for potential race conditions that we…
Skidamek May 22, 2026
7f0ae94
dont try injecting bridge on preload it doesnt work
Skidamek May 22, 2026
3c7edbf
Go back to tick method for better/earlier injection point for all ver…
Skidamek May 22, 2026
71b622c
autotester: fix TOCTOU races, poll jitter, log tail, connect health c…
Skidamek May 22, 2026
d7454a1
save but broken
Skidamek May 22, 2026
f321649
fix
Skidamek May 23, 2026
263e11e
more fixes
Skidamek May 23, 2026
f5dd4ab
patch fml race condition
Skidamek May 23, 2026
78cd77b
just disable the problematic early window
Skidamek May 23, 2026
cd49bbb
use fml11 for neoforge 26.1+ and update deps
Skidamek May 23, 2026
3bbb628
cache, job, key interruption, reliability fixes
Skidamek May 23, 2026
6de75de
always ensure_ready otherwise we might crash due to trying to connect…
Skidamek May 23, 2026
dd2f247
fixes
Skidamek May 27, 2026
cc30f92
Prepare autotester PR for upstream
Skidamek May 27, 2026
1c60980
fix forge 1.19.2 classloading crash in async data packet handler
Skidamek May 30, 2026
b77f36b
fix same classloader thread issue in fetchModpackContentAsync handle
Skidamek May 30, 2026
e5ec725
improvements
Skidamek May 31, 2026
595ce5f
remove debug deadlines
Skidamek May 31, 2026
142963a
stuf
Skidamek May 31, 2026
ebb60d7
remove debug logs
Skidamek Jun 1, 2026
5e14995
simplify stuff a little
Skidamek Jun 1, 2026
6385a2e
wait for resource load properly
Skidamek Jun 2, 2026
335eb64
autotester: review pass — fix login-flow regression, remove dead code…
Skidamek Jun 25, 2026
d258a20
autotester: wire up MC 26.2 on top of merged port (#496)
Skidamek Jun 26, 2026
2a34cb2
autotester: build the HeadlessMC client from our patched fork
Skidamek Jun 26, 2026
d3095c1
autotester: review-pass cleanup — drop dead deps/code, fix report agg…
Skidamek Jun 26, 2026
1a61ad4
remove fapi from forge buildscript
Skidamek Jun 27, 2026
c1ab64a
autotester: keep test code out of release jars; fix disable-update lo…
Skidamek Jun 27, 2026
d932b1a
autotester: declarative scenario engine (verbs, selectors, conditions…
Skidamek Jun 27, 2026
4c17715
autotester: simplify pass — dedup verbs, fix when/repeat on macros
Skidamek Jun 27, 2026
00be8a0
ci: run autotester engine tests (Docker-free) in CI
Skidamek Jun 27, 2026
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
16 changes: 16 additions & 0 deletions .github/workflows/autotester-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: step.autotester-tests

# Fast, Docker-free tests for the autotester step engine (selectors, conditions,
# templating, the executor, and the shipped scenarios run through a fake bridge).
on: [workflow_call]

jobs:
autotester-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Run engine tests
working-directory: autotester
run: uv run --group dev pytest
13 changes: 11 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ on:
type: string
required: false
default: ''
autotest:
description: bundle the autotester instrumentation into the jars (never for releases)
type: boolean
required: false
default: false

jobs:
build:
Expand All @@ -31,13 +36,17 @@ jobs:
- name: Execute Gradle build
run: |
chmod +x gradlew
flags=""
if [ "${{ inputs.autotest }}" = "true" ]; then
flags="-Pautomodpack.autotest"
fi
if [ -z "${{ inputs.target_subproject }}" ]; then
echo "Building all subprojects"
./gradlew build
./gradlew build $flags
else
args=$(echo "${{ inputs.target_subproject }}" | tr ',' '\n' | sed 's/$/:build/' | paste -sd ' ')
echo "Building with arguments=$args"
./gradlew $args
./gradlew $args $flags
fi
env:
BUILD_ID: ${{ github.run_number }}
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ jobs:
tests: # runs on linux and windows
uses: ./.github/workflows/tests.yml
secrets: inherit
autotester-tests: # autotester engine unit tests (no Docker)
uses: ./.github/workflows/autotester-tests.yml
secrets: inherit
build: # runs on linux
uses: ./.github/workflows/build.yml
secrets: inherit
142 changes: 142 additions & 0 deletions .github/workflows/ingame-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: In-game Tests

on:
workflow_dispatch:
inputs:
scenario:
description: "Autotest scenario"
default: "sync"
target:
description: "Target ID (or 'all')"
default: "all"
jobs:
description: "Parallel runs"
default: "1"

jobs:
prepare:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
scenario: ${{ steps.set-scenario.outputs.scenario }}
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
- id: set-matrix
run: |
TARGET="${{ github.event.inputs.target || 'all' }}"
ALL=$(uv run --project autotester python -c "import json,yaml; ids=[t['id'] for t in yaml.safe_load(open('autotester/targets.yaml')).get('targets',[])]; print(json.dumps(ids))")
if [ "$TARGET" = "all" ]; then
echo "matrix={\"target\":$ALL}" >> $GITHUB_OUTPUT
else
echo "matrix={\"target\":[\"$TARGET\"]}" >> $GITHUB_OUTPUT
fi
- id: set-scenario
run: |
echo "scenario=${{ github.event.inputs.scenario || 'sync' }}" >> $GITHUB_OUTPUT

unit:
uses: ./.github/workflows/autotester-tests.yml
secrets: inherit

build:
needs: [prepare, unit]
uses: ./.github/workflows/build.yml
with:
autotest: true
secrets: inherit

ingame:
needs: [build, prepare]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }}
steps:
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
- uses: actions/download-artifact@v6
with:
name: build-artifacts
path: merged/
- name: Build autotest client image
run: uv --project autotester run autotester build-images
- name: Run autotest
run: >
uv --project autotester run autotester run
--target "${{ matrix.target }}"
--scenario "${{ needs.prepare.outputs.scenario }}"
- uses: actions/upload-artifact@v6
if: always()
with:
name: autotester-${{ matrix.target }}
path: autotester/out

report:
needs: [ingame]
if: always()
runs-on: ubuntu-latest
steps:
- name: Install uv
uses: astral-sh/setup-uv@v7
- uses: actions/download-artifact@v6
with:
pattern: autotester-*
- name: Aggregate results
id: aggregate
run: |
cat > /tmp/aggregate.py << 'PYEOF'
import json, glob, os
results = []
for f in sorted(glob.glob("**/results.json", recursive=True)):
try:
data = json.load(open(f))
results.extend(data.get("results", []))
except Exception:
name = f.split(os.sep)[0] if os.sep in f else "unknown"
results.append({"target": name, "ok": False, "error": "results.json missing or invalid"})

total = len(results)
passed = sum(1 for r in results if r.get("ok"))
any_ok = passed == total

for r in results:
if not r.get("ok"):
err = r.get("error", "unknown error")
print(f"::error title={r['target']}::{err}")

summary = {"ok": any_ok, "total": total, "passed": passed, "failed": total - passed, "results": results}
with open("aggregated.json", "w") as f:
json.dump(summary, f, indent=2)

md = "## In-game Test Results\n\n"
md += f"**{'PASS' if any_ok else 'FAIL'}** — {passed}/{total} passed, {total - passed} failed\n\n"
md += "| Status | Target | Duration | Error |\n"
md += "|--------|--------|----------|-------|\n"
for r in results:
status = "✅" if r.get("ok") else "❌"
dur = f"{r.get('duration', 0):.1f}s" if "duration" in r else "-"
err = r.get("error", "") if not r.get("ok") else ""
md += f"| {status} | {r['target']} | {dur} | {err} |\n"

with open("summary.md", "w") as f:
f.write(md)

print(f"ok={str(any_ok).lower()}", file=open(os.environ["GITHUB_OUTPUT"], "a"))
PYEOF
python3 /tmp/aggregate.py
- uses: actions/upload-artifact@v6
with:
name: aggregated-results
path: |
aggregated.json
summary.md
- name: Post job summary
run: cat summary.md >> $GITHUB_STEP_SUMMARY
- name: Check overall result
if: steps.aggregate.outputs.ok != 'true'
run: |
echo "Some tests failed"
exit 1
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,11 @@ output/
/merged/
/core/automodpack/

dupes
dupes

# python

__pycache__/
*.egg-info/
autotester/out/
autotester/.hmc-cache/
Loading
Loading