|
| 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})" |
0 commit comments