forked from TheSuperHackers/GeneralsGameCode
-
-
Notifications
You must be signed in to change notification settings - Fork 45
377 lines (332 loc) · 15.4 KB
/
Copy pathrelease.yml
File metadata and controls
377 lines (332 loc) · 15.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
name: Release Pipeline
on:
workflow_dispatch:
inputs:
release_version:
description: "Release version tag (e.g., GeneralsX-Beta-3)"
required: true
type: string
release_mode:
description: "Release mode"
required: false
type: choice
options:
- Draft
- New Release
- Dry Run
default: Draft
concurrency:
group: release-${{ github.workflow }}-${{ inputs.release_version }}
cancel-in-progress: false
permissions:
contents: write
pull-requests: write
jobs:
# GeneralsX @build BenderAI 21/04/2026 Create git tag BEFORE builds so GitTag is set
# in the binary (git_watcher.cmake uses --exact-match, requires tag at build time).
# The job always runs so that dependent build jobs are never skipped on dry_run.
# The tag creation step is guarded at step level: no tag is pushed on dry_run.
create-tag:
runs-on: ubuntu-latest
steps:
# GeneralsX @build GitHubCopilot 08/05/2026 Use Node 24 compatible GitHub Actions major versions to remove runner deprecation warnings.
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
- name: Validate version input
run: |
VERSION="${{ inputs.release_version }}"
if [ -z "$VERSION" ]; then
echo "ERROR: release_version is required"
exit 1
fi
echo "Release version: $VERSION"
- name: Create and push git tag
if: inputs.release_mode != 'Dry Run'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ inputs.release_version }}"
if git show-ref --tags --verify --quiet "refs/tags/$VERSION"; then
echo "ERROR: Tag $VERSION already exists"
exit 1
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "$VERSION"
git push origin "$VERSION"
build-linux-flatpak:
needs: [create-tag]
uses: ./.github/workflows/build-linux-flatpak.yml
with:
preset: linux64-deploy
checkout_ref: refs/tags/${{ inputs.release_version }}
build-macos:
needs: [create-tag]
uses: ./.github/workflows/build-macos.yml
with:
preset: macos-vulkan
checkout_ref: refs/tags/${{ inputs.release_version }}
# GeneralsX @build BenderAI 21/04/2026 Roll back the pushed tag when anything
# downstream of create-tag fails, so a re-run with the same version is possible.
# Uses always() so this job runs even when upstream jobs are skipped/failed.
# prepare-release is intentionally excluded from needs: if a build fails,
# prepare-release is skipped (not failed), which would prevent cleanup from running.
cleanup-tag-on-failure:
if: >
always() &&
inputs.release_mode != 'Dry Run' &&
needs.create-tag.result == 'success' &&
(
needs.build-linux-flatpak.result == 'failure' ||
needs.build-macos.result == 'failure'
)
needs: [create-tag, build-linux-flatpak, build-macos]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
- name: Delete orphaned tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ inputs.release_version }}"
echo "Pipeline failed after tag was pushed. Deleting orphaned tag: $VERSION"
git push origin --delete "refs/tags/$VERSION" \
&& echo "Tag $VERSION deleted from remote." \
|| echo "Tag $VERSION not found on remote, nothing to delete."
prepare-release:
runs-on: ubuntu-latest
needs: [build-linux-flatpak, build-macos]
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0
fetch-tags: true
- name: Validate release inputs
run: |
VERSION="${{ inputs.release_version }}"
RELEASE_MODE="${{ inputs.release_mode }}"
if [ -z "$VERSION" ]; then
echo "ERROR: release_version is required"
exit 1
fi
echo "Release version: $VERSION"
echo "Release mode: $RELEASE_MODE"
if [ "$RELEASE_MODE" = "Dry Run" ]; then
echo "Dry run enabled. Tag/release creation will be skipped."
else
echo "Release tag is managed by create-tag job."
fi
- name: Detect latest release tag
id: latest
run: |
CURRENT_TAG="${{ inputs.release_version }}"
# GeneralsX @bugfix GitHubCopilot 21/04/2026 Exclude the in-flight release tag so changelog compares against the previous published release.
LATEST_TAG=$(git tag -l "GeneralsX*" --sort=-version:refname --merged HEAD | grep -Fxv "$CURRENT_TAG" | head -1)
if [ -z "$LATEST_TAG" ]; then
echo "latest_tag=" >> "$GITHUB_OUTPUT"
echo "latest_tag_date=" >> "$GITHUB_OUTPUT"
echo "first_release=true" >> "$GITHUB_OUTPUT"
else
LATEST_TAG_DATE=$(git log -1 --format=%cI "$LATEST_TAG")
echo "latest_tag=$LATEST_TAG" >> "$GITHUB_OUTPUT"
echo "latest_tag_date=$LATEST_TAG_DATE" >> "$GITHUB_OUTPUT"
echo "first_release=false" >> "$GITHUB_OUTPUT"
fi
- name: Download Linux Zero Hour Flatpak artifact
uses: actions/download-artifact@v8
with:
name: linux-flatpak-generalsxzh-linux64-deploy
path: artifacts/linux-flatpak-zh
- name: Download Linux Generals Flatpak artifact
uses: actions/download-artifact@v8
with:
name: linux-flatpak-generalsx-linux64-deploy
path: artifacts/linux-flatpak-generals
- name: Download macOS bundle artifact
uses: actions/download-artifact@v8
with:
name: macos-generalsxzh-app
path: artifacts/macos
- name: Download macOS Generals bundle artifact
uses: actions/download-artifact@v8
with:
name: macos-generalsx-app
path: artifacts/macos-generals
- name: Normalize bundle files for release assets
id: assets
env:
RELEASE_MODE: ${{ inputs.release_mode }}
run: |
mkdir -p release-assets
LINUX_ZH_FLATPAK=$(find artifacts/linux-flatpak-zh -name "*.flatpak" | head -1)
if [ -z "$LINUX_ZH_FLATPAK" ] || [ ! -f "$LINUX_ZH_FLATPAK" ]; then
echo "ERROR: Linux ZH Flatpak bundle not found in artifacts/linux-flatpak-zh"
find artifacts/linux-flatpak-zh -maxdepth 3 -type f || true
exit 1
fi
LINUX_GENERALS_FLATPAK=$(find artifacts/linux-flatpak-generals -name "*.flatpak" | head -1)
if [ -z "$LINUX_GENERALS_FLATPAK" ] || [ ! -f "$LINUX_GENERALS_FLATPAK" ]; then
echo "ERROR: Linux Generals Flatpak bundle not found in artifacts/linux-flatpak-generals"
find artifacts/linux-flatpak-generals -maxdepth 3 -type f || true
exit 1
fi
MAC_TAR=$(find artifacts/macos -name "*.tar" | head -1)
if [ -z "$MAC_TAR" ] || [ ! -f "$MAC_TAR" ]; then
echo "ERROR: macOS app tar not found in artifacts/macos"
find artifacts/macos -maxdepth 3 -type f || true
exit 1
fi
cp "$MAC_TAR" release-assets/GeneralsXZH-macos-arm64.app.tar
zip -j release-assets/macos-generalsxzh-app.tar.zip release-assets/GeneralsXZH-macos-arm64.app.tar
MAC_GENERALS_TAR=$(find artifacts/macos-generals -name "*.tar" | head -1)
if [ -z "$MAC_GENERALS_TAR" ] || [ ! -f "$MAC_GENERALS_TAR" ]; then
echo "ERROR: macOS Generals app tar not found in artifacts/macos-generals"
find artifacts/macos-generals -maxdepth 3 -type f || true
exit 1
fi
if [ "$RELEASE_MODE" = "Dry Run" ]; then
echo "Dry run enabled: skipping zip normalization to avoid large preview artifacts."
echo "linux_generals_asset=" >> "$GITHUB_OUTPUT"
echo "linux_asset=" >> "$GITHUB_OUTPUT"
echo "macos_generals_asset=" >> "$GITHUB_OUTPUT"
echo "macos_asset=" >> "$GITHUB_OUTPUT"
exit 0
fi
# GeneralsX @build GitHubCopilot 14/04/2026 Linux release now ships native Flatpak bundles instead of zip wrappers.
cp "$LINUX_ZH_FLATPAK" release-assets/GeneralsXZH-linux.flatpak
cp "$LINUX_GENERALS_FLATPAK" release-assets/GeneralsX-linux.flatpak
cp "$MAC_GENERALS_TAR" release-assets/GeneralsX-macos-arm64.app.tar
zip -j release-assets/macos-generalsx-app.tar.zip release-assets/GeneralsX-macos-arm64.app.tar
echo "linux_generals_asset=$GITHUB_WORKSPACE/release-assets/GeneralsX-linux.flatpak" >> "$GITHUB_OUTPUT"
echo "linux_asset=$GITHUB_WORKSPACE/release-assets/GeneralsXZH-linux.flatpak" >> "$GITHUB_OUTPUT"
echo "macos_generals_asset=$GITHUB_WORKSPACE/release-assets/macos-generalsx-app.tar.zip" >> "$GITHUB_OUTPUT"
echo "macos_asset=$GITHUB_WORKSPACE/release-assets/macos-generalsxzh-app.tar.zip" >> "$GITHUB_OUTPUT"
- name: Build changelog from local PRs only
id: changelog
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
LATEST_TAG: ${{ steps.latest.outputs.latest_tag }}
REPO: ${{ github.repository }}
run: |
PR_LINES_FILE=$(mktemp)
PR_DATA_FILE=$(mktemp)
COMMIT_RANGE="HEAD"
if [ -n "$LATEST_TAG" ]; then
COMMIT_RANGE="${LATEST_TAG}..HEAD"
fi
for SHA in $(git rev-list "$COMMIT_RANGE"); do
PR_JSON=$(gh api "repos/${REPO}/commits/${SHA}/pulls" 2>/dev/null || echo "[]")
# Keep only PRs that belong to this repository (exclude upstream PR URLs).
PR_ENTRY=$(echo "$PR_JSON" | jq -r --arg REPO "$REPO" '
map(select((.base.repo.full_name // "") == $REPO and (.html_url // "" | startswith("https://github.com/" + $REPO + "/pull/"))))
| sort_by(.number)
| reverse
| .[0]
| if . == null then empty else "\(.number)|\(.title)|\(.user.login)|\(.html_url)" end
')
if [ -n "$PR_ENTRY" ]; then
echo "$PR_ENTRY" >> "$PR_DATA_FILE"
fi
done
if [ -s "$PR_DATA_FILE" ]; then
sort -u -t'|' -k1,1n "$PR_DATA_FILE" | while IFS='|' read -r NUMBER TITLE AUTHOR URL; do
[ -z "$NUMBER" ] && continue
echo "- ${TITLE} by @${AUTHOR} in ${URL}" >> "$PR_LINES_FILE"
done
fi
if [ ! -s "$PR_LINES_FILE" ]; then
echo "- No pull requests found in this release range." >> "$PR_LINES_FILE"
fi
echo "pr_lines_file=$PR_LINES_FILE" >> "$GITHUB_OUTPUT"
echo "pr_data_file=$PR_DATA_FILE" >> "$GITHUB_OUTPUT"
- name: Build release notes markdown
id: notes
env:
LATEST_TAG: ${{ steps.latest.outputs.latest_tag }}
CURRENT_TAG: ${{ inputs.release_version }}
PR_LINES_FILE: ${{ steps.changelog.outputs.pr_lines_file }}
run: |
NOTES_FILE="release-assets/${{ inputs.release_version }}-notes.md"
NOTES_TXT_FILE="release-assets/${{ inputs.release_version }}-notes.txt"
mkdir -p release-assets
{
echo "> This is a **beta** release. Some bugs are still expected. If you run into any problems, please [open an issue](https://github.com/fbraz3/GeneralsX/issues) so we can investigate."
echo ""
if [ "${{ inputs.release_mode }}" = "Draft" ]; then
echo "# What's New"
echo ""
echo "*add-here manual release notes*"
echo ""
fi
echo "# Getting Started"
echo ""
echo "**Install the engine:** Follow the [Installation Guide](https://github.com/fbraz3/GeneralsX/blob/main/docs/HOWTO/INSTALLATION.md) to set up GeneralsX on your platform."
echo ""
echo "## Community Ports based on GeneralsX"
echo ""
echo "If you like GeneralsX, please also take a look into these projects"
echo ""
echo "* [Generals-Mac-iOS-iPad](https://github.com/ammaarreshi/Generals-Mac-iOS-iPad) - iOS port by [ammaarreshi](https://github.com/ammaarreshi)"
echo "* [Generals-Android](https://github.com/fadi-labib/Generals-Android) - Android port by [fadi-labib](https://github.com/fadi-labib)"
echo "* [GeneralsXWeb](https://github.com/meerzulee/GeneralsXWeb) - Web port by [meerzulee](https://github.com/meerzulee)"
echo ""
echo "## Changelog"
cat "$PR_LINES_FILE"
echo ""
if [ -n "$LATEST_TAG" ]; then
echo "**Full Changelog**: https://github.com/fbraz3/GeneralsX/compare/${LATEST_TAG}...${CURRENT_TAG}"
fi
} > "$NOTES_FILE"
cp "$NOTES_FILE" "$NOTES_TXT_FILE"
echo "notes_file=$GITHUB_WORKSPACE/$NOTES_FILE" >> "$GITHUB_OUTPUT"
echo "notes_txt_file=$GITHUB_WORKSPACE/$NOTES_TXT_FILE" >> "$GITHUB_OUTPUT"
- name: Upload dry-run release description
if: success() && inputs.release_mode == 'Dry Run'
uses: actions/upload-artifact@v7
with:
name: release-preview-${{ inputs.release_version }}
path: release-assets/${{ inputs.release_version }}-notes.txt
retention-days: 30
- name: Create GitHub release and upload assets
if: success() && inputs.release_mode != 'Dry Run'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DRAFT_FLAG=""
if [ "${{ inputs.release_mode }}" = "Draft" ]; then
DRAFT_FLAG="--draft"
fi
gh release create "${{ inputs.release_version }}" \
$DRAFT_FLAG \
--title "GeneralsX - ${{ inputs.release_version }}" \
--notes-file "${{ steps.notes.outputs.notes_file }}" \
"${{ steps.assets.outputs.linux_generals_asset }}" \
"${{ steps.assets.outputs.linux_asset }}" \
"${{ steps.assets.outputs.macos_generals_asset }}" \
"${{ steps.assets.outputs.macos_asset }}"
- name: Summary
run: |
echo "## Release Pipeline Summary" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "- Tag: ${{ inputs.release_version }}" >> "$GITHUB_STEP_SUMMARY"
echo "- Mode: ${{ inputs.release_mode }}" >> "$GITHUB_STEP_SUMMARY"
echo "- Linux asset (Generals): GeneralsX-linux.flatpak" >> "$GITHUB_STEP_SUMMARY"
echo "- Linux asset: GeneralsXZH-linux.flatpak" >> "$GITHUB_STEP_SUMMARY"
echo "- macOS asset (Generals): macos-generalsx-app.tar.zip" >> "$GITHUB_STEP_SUMMARY"
echo "- macOS asset: macos-generalsxzh-app.tar.zip" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
if [ "${{ inputs.release_mode }}" = "Dry Run" ]; then
echo "No GitHub release was created. Download preview artifacts from this run." >> "$GITHUB_STEP_SUMMARY"
elif [ "${{ inputs.release_mode }}" = "Draft" ]; then
echo "Draft release created and assets attached." >> "$GITHUB_STEP_SUMMARY"
else
echo "Release created and assets attached." >> "$GITHUB_STEP_SUMMARY"
fi