Skip to content

Commit f9ef86b

Browse files
Merge branch 'jpackage-releases'
# Conflicts: # build.gradle.kts
2 parents 55dd5c6 + cab62d4 commit f9ef86b

File tree

29 files changed

+1092
-229
lines changed

29 files changed

+1092
-229
lines changed
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
name: Package Installers (jpackage)
2+
3+
permissions:
4+
contents: write
5+
actions: read
6+
7+
on:
8+
workflow_dispatch:
9+
inputs:
10+
version:
11+
description: "Release version (e.g., 1.2.3)"
12+
required: true
13+
type: string
14+
workflow_run:
15+
workflows: [ "Create Release" ]
16+
types:
17+
- completed
18+
19+
jobs:
20+
build-package:
21+
if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}
22+
name: Build installers on ${{ matrix.os }}
23+
runs-on: ${{ matrix.os }}
24+
env:
25+
VERSION: ${{ github.event.inputs.version }}
26+
strategy:
27+
fail-fast: false
28+
matrix:
29+
os: [ ubuntu-latest, windows-latest, macos-latest ]
30+
31+
steps:
32+
- name: Checkout
33+
uses: actions/checkout@v4
34+
35+
- name: Set up Temurin JDK 21 (for jpackage)
36+
uses: actions/setup-java@v4
37+
with:
38+
distribution: temurin
39+
java-version: '21'
40+
cache: 'gradle'
41+
42+
- name: Set up Gradle
43+
uses: gradle/gradle-build-action@v3
44+
45+
- name: Ensure WiX 3.x available (Windows)
46+
if: matrix.os == 'windows-latest'
47+
shell: powershell
48+
run: |
49+
$wix = Get-Command candle.exe -ErrorAction SilentlyContinue
50+
if ($wix) {
51+
Write-Host "WiX already available: $($wix.Path)"
52+
candle.exe -? | Select-Object -First 1
53+
exit 0
54+
} else {
55+
choco install wixtoolset -y --no-progress
56+
}
57+
58+
- name: Install Linux packaging prerequisites
59+
if: matrix.os == 'ubuntu-latest'
60+
run: |
61+
sudo apt-get update
62+
sudo apt-get install -y rpm fakeroot libfuse2
63+
64+
- name: Verify Java and jpackage
65+
run: |
66+
java -version
67+
jpackage --version
68+
69+
- name: Build and create installers for this OS (quiet)
70+
run: |
71+
set -e
72+
# Ensure log directory exists
73+
mkdir -p build
74+
# Run Gradle quietly and capture all output to a log. On failure, print only the tail.
75+
./gradlew --no-daemon --stacktrace --quiet --console=plain -Dorg.gradle.warning.mode=none stageAllInstallers \
76+
> build/ci-gradle.log 2>&1 \
77+
|| (echo "Gradle build failed — showing last 400 lines of log:" && tail -n 400 build/ci-gradle.log && exit 1)
78+
echo "Gradle build succeeded. (Logs suppressed; see build/ci-gradle.log in the artifact if needed.)"
79+
shell: bash
80+
81+
- name: Re-run macOS with deep jpackage diagnostics (only on macOS)
82+
if: matrix.os == 'macos-latest' && failure()
83+
run: |
84+
echo "Re-running macOS packaging with --debug to surface jpackage stderr"
85+
./gradlew --no-daemon --debug -PciVerbose=true :booter:jpackageMac :recorder:jpackageMac
86+
shell: bash
87+
88+
- name: Import GPG key (Linux/macOS)
89+
if: matrix.os != 'windows-latest'
90+
run: echo "$GPG_PRIVATE_KEY" | gpg --batch --import
91+
env:
92+
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
93+
94+
- name: Import GPG key (Windows)
95+
if: matrix.os == 'windows-latest'
96+
shell: pwsh
97+
run: |
98+
Set-Content -Path gpg-key.asc -Value $env:GPG_PRIVATE_KEY -NoNewline
99+
gpg --batch --import gpg-key.asc
100+
env:
101+
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
102+
103+
- name: Generate SHA256 checksums (Linux/macOS)
104+
if: matrix.os != 'windows-latest'
105+
run: |
106+
cd build/dist
107+
find . -type f -exec sha256sum {} + > SHA256SUMS
108+
109+
- name: Generate SHA256 checksums (Windows)
110+
if: matrix.os == 'windows-latest'
111+
shell: pwsh
112+
run: |
113+
Set-Location build/dist
114+
Get-ChildItem -Recurse -File | ForEach-Object {
115+
$hash = Get-FileHash $_.FullName -Algorithm SHA256
116+
"$($hash.Hash) $($_.FullName.Substring((Get-Location).Path.Length + 1))" | Out-File -Encoding ascii -Append SHA256SUMS
117+
}
118+
119+
- name: Sign SHA256SUMS (Linux/macOS)
120+
if: matrix.os != 'windows-latest'
121+
run: |
122+
cd build/dist
123+
gpg --batch --yes --pinentry-mode loopback \
124+
--passphrase "$GPG_PASSPHRASE" \
125+
--armor --detach-sign SHA256SUMS
126+
env:
127+
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
128+
129+
- name: Sign SHA256SUMS (Windows)
130+
if: matrix.os == 'windows-latest'
131+
shell: pwsh
132+
run: |
133+
Set-Location build/dist
134+
gpg --batch --yes --pinentry-mode loopback --passphrase "$env:GPG_PASSPHRASE" --armor --detach-sign SHA256SUMS
135+
env:
136+
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
137+
138+
- name: Upload installers
139+
if: always()
140+
uses: actions/upload-artifact@v4
141+
with:
142+
name: installers-${{ matrix.os }}
143+
path: |
144+
build/dist/**/*
145+
build/ci-gradle.log
146+
build/dist/SHA256SUMS
147+
build/dist/SHA256SUMS.asc
148+
if-no-files-found: warn
149+
150+
upload-to-release:
151+
name: Upload installers to GitHub Release
152+
needs: build-package
153+
runs-on: ubuntu-latest
154+
if: github.event_name == 'workflow_dispatch' || github.event_name == 'push'
155+
steps:
156+
- name: Download all installer artifacts
157+
uses: actions/download-artifact@v4
158+
with:
159+
path: all-installers
160+
161+
- name: List downloaded files (debug)
162+
run: |
163+
find all-installers
164+
165+
- name: Deduplicate SHA256SUMS files
166+
run: |
167+
# Keep only the first found SHA256SUMS and SHA256SUMS.asc
168+
find all-installers -name 'SHA256SUMS' | head -n 1 | xargs -I{} cp {} all-installers/SHA256SUMS
169+
find all-installers -name 'SHA256SUMS.asc' | head -n 1 | xargs -I{} cp {} all-installers/SHA256SUMS.asc
170+
# Remove all other SHA256SUMS and SHA256SUMS.asc
171+
find all-installers -name 'SHA256SUMS' ! -path 'all-installers/SHA256SUMS' -delete
172+
find all-installers -name 'SHA256SUMS.asc' ! -path 'all-installers/SHA256SUMS.asc' -delete
173+
174+
- name: Upload installers to GitHub Release
175+
uses: softprops/action-gh-release@v2
176+
with:
177+
tag_name: v${{ github.event.inputs.version || env.VERSION }}
178+
files: |
179+
all-installers/**/*.msi
180+
all-installers/**/*.deb
181+
all-installers/**/*.rpm
182+
all-installers/**/*.pkg
183+
all-installers/SHA256SUMS
184+
all-installers/SHA256SUMS.asc
185+
env:
186+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

booter/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ The booter is run using the `java` command from the command line:
3333
java -jar robocode-tankroyale-booter-x.y.z.jar
3434
```
3535

36+
## Packaging (jpackage)
37+
38+
See the packaging guide in [./jpackage.md](./jpackage.md).
39+
3640
## Main options
3741

3842
The booter has some options to display help, but also version information:

booter/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,11 @@ tasks {
115115
}
116116
}
117117
}
118+
119+
// Opt-in to centralized jpackage tasks (configured in root build.gradle.kts)
120+
extra["useJpackage"] = false
121+
extra["jpackageAppName"] = title
122+
extra["jpackageMainJar"] = finalJar
123+
extra["jpackageMainClass"] = jarManifestMainClass
124+
extra["jpackageDependsOn"] = "proguard"
118125
}

booter/jpackage-config.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"appName": "Robocode Tank Royale Booter",
3+
"vendor": "robocode.dev",
4+
"version": "${version}",
5+
"description": "Robocode Tank Royale is a programming game where you code autonomous virtual tanks to battle in an arena",
6+
"licenseUrl": "https://github.com/robocode-dev/tank-royale/blob/main/LICENSE",
7+
"homepage": "https://robocode.dev",
8+
"installDirName": "robocode-tank-royale",
9+
"mainJar": "build/libs/robocode-tankroyale-booter-${version}.jar",
10+
"mainClass": "dev.robocode.tankroyale.booter.MainKt",
11+
"icons": {
12+
"windows": "../gfx/Tank/Tank.ico",
13+
"mac": "../gfx/Tank/Tank.icns",
14+
"linux": "../gfx/Tank/Tank.png"
15+
}
16+
}

booter/jpackage.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Packaging (jpackage)
2+
3+
This component is packaged as a runnable JAR with all runtime dependencies included and then compacted via ProGuard.
4+
5+
- App name: Robocode Tank Royale Booter
6+
- Main class: dev.robocode.tankroyale.booter.BooterKt
7+
- Main JAR pattern (Gradle output): build/libs/robocode-tankroyale-booter-<version>.jar
8+
- Vendor: robocode.dev
9+
- Version: inherited from root gradle.properties
10+
- Required resources: none beyond bundled JAR contents
11+
12+
When creating a native installer with jpackage, use parameters equivalent to:
13+
14+
- --name "Robocode Tank Royale Booter"
15+
- --main-class dev.robocode.tankroyale.booter.BooterKt
16+
- --main-jar robocode-tankroyale-booter-<version>.jar
17+
- --app-version <version>
18+
- --vendor robocode.dev
19+
- --icon <platform-specific icon path> (to be provided)
20+
21+
Note: The Gradle build produces a fat/ProGuarded JAR; you can point jpackage at that output.

0 commit comments

Comments
 (0)