Skip to content

Commit a7f42fa

Browse files
committed
Add automated ET:Legacy i386 server build workflow
This workflow automates the creation of a LinuxGSM-compatible archive by combining the latest ET:Legacy i386 server binary with original Enemy Territory 2.60b pak files. It handles version scraping, binary renaming, and weekly release publishing.
1 parent 558ab88 commit a7f42fa

2 files changed

Lines changed: 235 additions & 0 deletions

File tree

.github/workflows/build.yml

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
name: Build ET:Legacy i386 Server for LinuxGSM
2+
3+
on:
4+
schedule:
5+
- cron: '0 2 * * 1' # Every Monday at 02:00 UTC
6+
workflow_dispatch:
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
18+
- name: Get ETL download URL and version
19+
id: etl
20+
run: |
21+
echo "Fetching ETL download page..."
22+
DOWNLOAD_HTML=$(curl -sSf "https://www.etlegacy.com/download")
23+
24+
# Extract the Linux i386 archive download URL.
25+
ETL_URL=$(echo "$DOWNLOAD_HTML" | python3 - <<'EOF'
26+
import sys, re
27+
content = sys.stdin.read()
28+
m = re.search(
29+
r'data-href="(https://www\.etlegacy\.com/download/file/\d+)">i386 archive<',
30+
content
31+
)
32+
if m:
33+
print(m.group(1))
34+
else:
35+
sys.exit(1)
36+
EOF
37+
)
38+
39+
if [[ -z "$ETL_URL" ]]; then
40+
echo "::error::Could not find Linux i386 archive link on the ETL download page"
41+
exit 1
42+
fi
43+
44+
# Resolve filename and version from the Content-Disposition header
45+
FILENAME=$(curl -sSI "$ETL_URL" \
46+
| grep -i 'content-disposition' \
47+
| tr -d '\r' \
48+
| grep -oP 'filename=\K\S+')
49+
50+
VERSION=$(echo "$FILENAME" | grep -oP '(?<=etlegacy-v)[0-9.]+')
51+
52+
if [[ -z "$VERSION" ]]; then
53+
echo "::error::Failed to parse ETL version from filename: $FILENAME"
54+
exit 1
55+
fi
56+
57+
echo "url=$ETL_URL" >> "$GITHUB_OUTPUT"
58+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
59+
echo "filename=$FILENAME" >> "$GITHUB_OUTPUT"
60+
echo "ETL version : $VERSION"
61+
echo "Download URL: $ETL_URL"
62+
63+
- name: Check for existing release
64+
id: check
65+
env:
66+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
67+
run: |
68+
VERSION="${{ steps.etl.outputs.version }}"
69+
if gh release view "v${VERSION}" --repo "${{ github.repository }}" &>/dev/null; then
70+
echo "exists=true" >> "$GITHUB_OUTPUT"
71+
echo "Release v${VERSION} already exists — skipping build."
72+
else
73+
echo "exists=false" >> "$GITHUB_OUTPUT"
74+
echo "Release v${VERSION} not found — proceeding with build."
75+
fi
76+
77+
- name: Download ETL Linux i386 archive
78+
if: steps.check.outputs.exists == 'false'
79+
run: |
80+
echo "Downloading ET:Legacy v${{ steps.etl.outputs.version }} Linux i386 archive..."
81+
curl -sSfL -o etlegacy-i386.tar.gz "${{ steps.etl.outputs.url }}"
82+
ls -lh etlegacy-i386.tar.gz
83+
84+
- name: Download Enemy Territory 2.60b files
85+
if: steps.check.outputs.exists == 'false'
86+
run: |
87+
echo "Downloading Enemy Territory 2.60b files..."
88+
curl -sSfL -o et260b.tar.xz \
89+
"http://linuxgsm.download/WolfensteinEnemyTerritory/enemy-territory.260b.tar.xz"
90+
ls -lh et260b.tar.xz
91+
92+
- name: Build combined server archive
93+
if: steps.check.outputs.exists == 'false'
94+
run: |
95+
VERSION="${{ steps.etl.outputs.version }}"
96+
OUTPUT="etlegacy-v${VERSION}-i386-et-260b.tar.xz"
97+
98+
# ── Extract ETL archive ───────────────────────────────────────────────
99+
mkdir -p build/etl
100+
tar xzf etlegacy-i386.tar.gz -C build/etl
101+
102+
# Locate the extracted ETL directory (e.g. etlegacy-v2.83.2-x86_64/)
103+
ETL_DIR=$(find build/etl -maxdepth 1 -type d -name "etlegacy-*" | head -1)
104+
if [[ -z "$ETL_DIR" ]]; then
105+
echo "::error::Could not find ETL directory inside the archive"
106+
ls -la build/etl/
107+
exit 1
108+
fi
109+
echo "ETL directory: $ETL_DIR"
110+
111+
# ── Rename server binary for LinuxGSM compatibility ──────────────────
112+
# LinuxGSM etlserver expects the binary to be named 'etlded'.
113+
if [[ -f "${ETL_DIR}/etlded.i386" ]]; then
114+
mv "${ETL_DIR}/etlded.i386" "${ETL_DIR}/etlded"
115+
chmod +x "${ETL_DIR}/etlded"
116+
echo "Renamed etlded.i386 → etlded"
117+
elif [[ -f "${ETL_DIR}/etlded" ]]; then
118+
chmod +x "${ETL_DIR}/etlded"
119+
echo "etlded binary already named correctly"
120+
else
121+
echo "::error::etlded binary not found in the ETL archive"
122+
ls -la "${ETL_DIR}/"
123+
exit 1
124+
fi
125+
126+
# ── Extract ET 2.60b files and copy pak files to etmain/ ─────────────
127+
# ET:Legacy requires the original Enemy Territory pak files (pak0–pak2)
128+
# to be present in etmain/ alongside the ETL mod files.
129+
mkdir -p build/et260b
130+
tar xJf et260b.tar.xz -C build/et260b
131+
132+
mkdir -p "${ETL_DIR}/etmain"
133+
134+
PAK_COUNT=0
135+
while IFS= read -r -d '' pak; do
136+
cp "$pak" "${ETL_DIR}/etmain/"
137+
echo "Copied: $(basename "$pak")"
138+
((PAK_COUNT++))
139+
done < <(find build/et260b -name "pak*.pk3" -print0)
140+
141+
if [[ $PAK_COUNT -eq 0 ]]; then
142+
echo "::error::No pak*.pk3 files found in the ET 2.60b archive"
143+
echo "ET 2.60b archive top-level contents:"
144+
ls -la build/et260b/ | head -30
145+
exit 1
146+
fi
147+
echo "Copied ${PAK_COUNT} pak file(s) to etmain/"
148+
149+
# ── Show the final directory structure ───────────────────────────────
150+
echo "Server root:"
151+
ls -la "${ETL_DIR}/"
152+
echo "etmain/:"
153+
ls -la "${ETL_DIR}/etmain/"
154+
155+
# ── Pack flat archive (no outer directory wrapper) ───────────────────
156+
tar cJf "$OUTPUT" -C "${ETL_DIR}" .
157+
158+
MD5=$(md5sum "$OUTPUT" | cut -d' ' -f1)
159+
echo "Created : $OUTPUT"
160+
ls -lh "$OUTPUT"
161+
echo "MD5 : $MD5"
162+
163+
# Pass to subsequent steps
164+
echo "OUTPUT=$OUTPUT" >> "$GITHUB_ENV"
165+
echo "MD5=$MD5" >> "$GITHUB_ENV"
166+
167+
- name: Create GitHub Release
168+
if: steps.check.outputs.exists == 'false'
169+
env:
170+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
171+
run: |
172+
VERSION="${{ steps.etl.outputs.version }}"
173+
174+
gh release create "v${VERSION}" \
175+
--title "ET:Legacy v${VERSION} i386 Server for LinuxGSM" \
176+
--notes "## ET:Legacy v${VERSION} Linux i386 Server for LinuxGSM
177+
178+
Built from:
179+
- [ET:Legacy v${VERSION}](https://www.etlegacy.com/download) Linux i386 server archive
180+
- Enemy Territory 2.60b game files (pak0.pk3, pak1.pk3, pak2.pk3)
181+
182+
For use with [LinuxGSM etlserver](https://linuxgsm.com/servers/etlserver/).
183+
184+
### File details
185+
\`\`\`
186+
Filename : ${OUTPUT}
187+
MD5 : ${MD5}
188+
\`\`\`
189+
190+
### LinuxGSM download URL
191+
\`\`\`
192+
https://github.com/${{ github.repository }}/releases/download/v${VERSION}/${OUTPUT}
193+
\`\`\`" \
194+
"$OUTPUT"
195+
196+
echo "Release v${VERSION} created with ${OUTPUT} (MD5: ${MD5})"

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,40 @@
11
# etlserver-build
2+
3+
Automated GitHub Actions build that combines the latest
4+
[ET:Legacy](https://www.etlegacy.com/) Linux i386 server with the original
5+
Enemy Territory 2.60b game files, producing a single archive ready for use
6+
with [LinuxGSM etlserver](https://linuxgsm.com/servers/etlserver/).
7+
8+
## Why this exists
9+
10+
ET:Legacy requires both its own server binary **and** the original Enemy
11+
Territory pak files (`pak0.pk3`, `pak1.pk3`, `pak2.pk3`) to run. LinuxGSM
12+
currently ships an i386 combined package, but this repo automates keeping it
13+
up to date with the latest ET:Legacy release.
14+
15+
## What the workflow does
16+
17+
1. Scrapes `https://www.etlegacy.com/download` to find the latest stable
18+
Linux i386 archive URL.
19+
2. Checks whether a release already exists for that version — skips the build
20+
if it does.
21+
3. Downloads the ETL Linux x86_64 archive and the Enemy Territory 2.60b files.
22+
4. Renames `etlded.i386``etlded` for LinuxGSM compatibility.
23+
5. Merges the original ET `pak*.pk3` files into `etmain/`.
24+
6. Packages everything into a flat `etlegacy-vX.Y.Z-i386-et-260b.tar.xz`
25+
archive and publishes a GitHub Release.
26+
27+
## Schedule
28+
29+
The workflow runs every **Monday at 02:00 UTC** and can also be triggered
30+
manually via `workflow_dispatch`.
31+
32+
## Using the release with LinuxGSM
33+
34+
Update the `etl` entry in LinuxGSM's `install_server_files.sh` to point at
35+
the release asset URL shown in the release notes, e.g.:
36+
37+
```
38+
https://github.com/GameServerManagers/etlserver-build/releases/download/vX.Y.Z/etlegacy-vX.Y.Z-x86_64-et-260b.tar.xz
39+
```
40+

0 commit comments

Comments
 (0)