Skip to content

Commit cd4ac1e

Browse files
authored
Merge pull request #44 from palantir/github-actions
GitHub actions
2 parents 8251539 + f39760a commit cd4ac1e

7 files changed

Lines changed: 204 additions & 82 deletions

File tree

.circleci/config.yml

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,11 @@ jobs:
1717
name: Copy Assets
1818
command: |
1919
cp ./build/libs/onb-classic-*-all.jar ~/assets-cache/onb-classic-all.jar
20-
- run:
21-
name: Get Version
22-
command: |
23-
onbVersion=$(./gradlew -q showVersion)
24-
echo $onbVersion > ~/assets-cache/onbversion.txt
2520
- persist_to_workspace:
2621
root: ~/assets-cache
2722
paths:
2823
- ./*
2924

30-
deploy-snapshot:
31-
docker: [{ image: 'cimg/openjdk:21.0' }]
32-
steps:
33-
- checkout
34-
- attach_workspace:
35-
at: ~/assets-cache
36-
- run:
37-
name: Publish snapshot
38-
command: if [[ -z "$CIRCLE_PR_NUMBER" ]]; then ./scripts/publish.sh snapshot; else echo "Skipping...not from the official repo."; fi
39-
40-
deploy-release:
41-
docker: [{ image: 'cimg/openjdk:21.0' }]
42-
steps:
43-
- checkout
44-
- attach_workspace:
45-
at: ~/assets-cache
46-
- run:
47-
name: Publish release
48-
command: if [[ -z "$CIRCLE_PR_NUMBER" ]]; then ./scripts/publish.sh release; else echo "Skipping...not from the official repo."; fi
49-
5025
circle-all:
5126
docker: [{ image: 'busybox:1.36.1@sha256:6d9ac9237a84afe1516540f40a0fafdc86859b2141954b4d643af7066d598b74' }]
5227
resource_class: small
@@ -58,18 +33,6 @@ workflows:
5833
build-and-deploy:
5934
jobs:
6035
- build
61-
- deploy-snapshot:
62-
requires:
63-
- build
64-
filters:
65-
branches:
66-
only: /^develop.*/
67-
- deploy-release:
68-
requires:
69-
- build
70-
filters:
71-
branches:
72-
only: /^release.*/
7336
- circle-all:
7437
requires: [ build ]
7538
filters: { tags: { only: /.*/ } }

.github/workflows/release.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Build and Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*' # Trigger on version tags like v1.0.0, v2.1.3, etc.
7+
workflow_dispatch: # Allow manual triggering
8+
9+
permissions:
10+
contents: write # Required to create releases and upload assets
11+
12+
jobs:
13+
build-and-release:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0 # Full history needed for git-version plugin
20+
21+
- name: Set up JDK 21
22+
uses: actions/setup-java@v4
23+
with:
24+
java-version: '21'
25+
distribution: 'temurin'
26+
cache: 'gradle'
27+
28+
- name: Grant execute permission for gradlew
29+
run: chmod +x gradlew
30+
31+
- name: Build with Gradle
32+
run: ./gradlew shadowJar
33+
34+
- name: Get version
35+
id: version
36+
run: |
37+
VERSION=$(./gradlew -q showVersion)
38+
echo "version=$VERSION" >> $GITHUB_OUTPUT
39+
echo "Building version: $VERSION"
40+
41+
- name: Find JAR file
42+
id: jar
43+
run: |
44+
JAR_FILE=$(find ./build/libs -name "onb-classic-*-all.jar" | head -n 1)
45+
echo "jar_file=$JAR_FILE" >> $GITHUB_OUTPUT
46+
echo "Found JAR: $JAR_FILE"
47+
48+
- name: Create GitHub Release
49+
uses: softprops/action-gh-release@v2
50+
with:
51+
name: Release ${{ steps.version.outputs.version }}
52+
draft: false
53+
prerelease: false
54+
generate_release_notes: true
55+
files: |
56+
${{ steps.jar.outputs.jar_file }}
57+
env:
58+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Docs: [Docs](https://palantir.github.io/onb-classic/), source in docs/source
1717

1818
Releases: [Releases on Github](https://github.com/palantir/onb-classic/releases)
1919

20+
**Platform Support**: Release JARs include JavaFX native libraries for Windows (x86-64), Linux (x86-64),
21+
and macOS (ARM64/Apple Silicon). Intel Macs and ARM Linux are not supported in releases;
22+
users on those platforms can [build from source for their architecture](https://palantir.github.io/onb-classic/development/index.html#building-for-different-platforms).
23+
2024
![ONB-Classic Booting](./docs/onb_booting.gif)
2125

2226
## Running
@@ -32,11 +36,6 @@ Releases: [Releases on Github](https://github.com/palantir/onb-classic/releases)
3236
The build will finish and put resources in "./build/libs/", onb-classic.jar has no dependencies included,
3337
while onb-classic-all.jar has all its dependencies bundled into the jar.
3438

35-
## Open Source Plans
36-
37-
1. Clean up code more
38-
- replace all PUBLIC_URL_NEEDED
39-
4039
## Licenses
4140

4241
This project is under Apache 2.0, some of the core TFTP files come from an old version of Apache Net Commons.

build.gradle

Lines changed: 111 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,30 +41,124 @@ apply plugin: 'com.palantir.jdks.latest'
4141
group = 'com.palantir.onb'
4242
version gitVersion()
4343

44+
def javafxVersion = "21.0.9"
45+
def javafxModules = ['base', 'controls', 'fxml', 'graphics']
46+
47+
// Per-platform configs hold the classifier-specific native jars that get folded
48+
// into the shadow jar. Attributes are required: openjfx publishes Gradle Module
49+
// Metadata with multiple variants (winRuntime/linuxRuntime/macRuntime/etc.) and
50+
// without these, Gradle can't pick one and resolution fails with an ambiguity
51+
// error. The classifier in the coordinate pins the file *after* variant
52+
// selection; attributes drive the variant selection itself.
53+
//
54+
// Apple Silicon only on macOS. Intel Macs (pre-2020) are unsupported; users on
55+
// those machines can build from source against the :mac classifier themselves.
56+
configurations {
57+
javafxWin {
58+
attributes {
59+
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
60+
attribute(OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, objects.named(OperatingSystemFamily, 'windows'))
61+
attribute(MachineArchitecture.ARCHITECTURE_ATTRIBUTE, objects.named(MachineArchitecture, 'x86-64'))
62+
}
63+
}
64+
javafxLinux {
65+
attributes {
66+
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
67+
attribute(OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, objects.named(OperatingSystemFamily, 'linux'))
68+
attribute(MachineArchitecture.ARCHITECTURE_ATTRIBUTE, objects.named(MachineArchitecture, 'x86-64'))
69+
}
70+
}
71+
javafxMacAarch64 {
72+
attributes {
73+
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_RUNTIME))
74+
attribute(OperatingSystemFamily.OPERATING_SYSTEM_ATTRIBUTE, objects.named(OperatingSystemFamily, 'macos'))
75+
attribute(MachineArchitecture.ARCHITECTURE_ATTRIBUTE, objects.named(MachineArchitecture, 'aarch64'))
76+
}
77+
}
78+
}
79+
80+
def addJavafx = { String classifier, String configName ->
81+
javafxModules.each { m ->
82+
dependencies.add(configName, "org.openjfx:javafx-${m}:${javafxVersion}:${classifier}")
83+
}
84+
}
85+
addJavafx('win', 'javafxWin')
86+
addJavafx('linux', 'javafxLinux')
87+
addJavafx('mac-aarch64', 'javafxMacAarch64')
88+
4489
jar {
4590
manifest {
4691
attributes 'Main-Class': 'com.palantir.onb.Core'
4792
}
4893
}
4994

95+
shadowJar {
96+
archiveClassifier.set('all')
97+
manifest {
98+
attributes 'Main-Class': 'com.palantir.onb.Core'
99+
}
100+
mergeServiceFiles()
101+
102+
// Reproducible builds: same git SHA -> byte-identical jar
103+
preserveFileTimestamps = false
104+
reproducibleFileOrder = true
105+
106+
// Bundle natives for every supported platform. The openjfx plugin is
107+
// configured with `configuration = 'compileOnly'` below so runtimeClasspath
108+
// does NOT contain host-arch natives — output is independent of build host.
109+
configurations = [
110+
project.configurations.runtimeClasspath,
111+
project.configurations.javafxWin,
112+
project.configurations.javafxLinux,
113+
project.configurations.javafxMacAarch64,
114+
]
115+
}
116+
117+
// Fail the build if shadowJar is missing natives for any supported platform.
118+
// Catches future regressions (renamed config, wrong classifier, etc.) at build
119+
// time rather than at a user's desktop.
120+
tasks.register('verifyShadowJarNatives') {
121+
dependsOn shadowJar
122+
def jarProvider = shadowJar.archiveFile
123+
doLast {
124+
def jar = jarProvider.get().asFile
125+
def entries = new java.util.zip.ZipFile(jar).withCloseable { zf ->
126+
zf.entries().collect { it.name }
127+
}
128+
def checks = [
129+
win : entries.any { it.endsWith('glass.dll') },
130+
linux : entries.any { it.endsWith('libglass.so') },
131+
macAarch64 : entries.any { it.endsWith('libglass.dylib') },
132+
]
133+
def missing = checks.findAll { !it.value }.collect { it.key }
134+
if (missing) {
135+
throw new GradleException("shadowJar is missing JavaFX natives for: ${missing}. " +
136+
"Check the per-platform configurations and openjfx plugin setup.")
137+
}
138+
logger.lifecycle("shadowJar natives present for: ${checks.keySet().join(', ')}")
139+
}
140+
}
141+
tasks.named('build') { dependsOn 'verifyShadowJarNatives' }
142+
50143
java {
51144
modularity.inferModulePath = true
52145
}
53146

54147
// Generate version.properties file from git tags
55148
tasks.register('generateVersionProperties') {
56-
def outputDir = file("${buildDir}/generated/resources")
149+
def outputDir = layout.buildDirectory.dir('generated/resources')
57150
outputs.dir outputDir
151+
def versionString = project.version.toString()
58152
doLast {
59-
outputDir.mkdirs()
60-
def propsFile = file("${outputDir}/version.properties")
61-
propsFile.text = "version=${project.version}\n"
153+
def dir = outputDir.get().asFile
154+
dir.mkdirs()
155+
new File(dir, 'version.properties').text = "version=${versionString}\n"
62156
}
63157
}
64158

65159
processResources {
66160
dependsOn generateVersionProperties
67-
from("${buildDir}/generated/resources") {
161+
from(layout.buildDirectory.dir('generated/resources')) {
68162
include 'version.properties'
69163
}
70164
}
@@ -114,12 +208,13 @@ dependencyUpdates {
114208
}
115209
}
116210

211+
// `configuration = 'compileOnly'` keeps JavaFX natives off runtimeClasspath
212+
// so the shadow jar's contents are a pure function of the explicit per-platform
213+
// configs above — not of whatever host architecture happened to run gradle.
117214
javafx {
118-
version = "21.0.9"
119-
modules = [
120-
'javafx.controls',
121-
'javafx.fxml'
122-
]
215+
version = javafxVersion
216+
modules = ['javafx.controls', 'javafx.fxml']
217+
configuration = 'compileOnly'
123218
}
124219

125220
tasks.withType(Test) {
@@ -172,19 +267,20 @@ def tomcatVersion = '10.1.49'
172267
dependencies {
173268
implementation group: 'com.palantir.isofilereader', name: 'isofilereader', version: '0.6.2'
174269

175-
// For dependencies
176270
implementation 'com.google.code.gson:gson:2.13.2'
177271

178-
implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: "$tomcatVersion"
272+
implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core', version: "$tomcatVersion"
179273
implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper', version: "$tomcatVersion"
180-
implementation group: 'org.apache.tomcat', name: 'tomcat-jasper', version: "$tomcatVersion"
181-
implementation group: 'org.apache.tomcat', name: 'tomcat-jasper-el', version: "$tomcatVersion"
182-
implementation group: 'org.apache.tomcat', name: 'tomcat-jsp-api', version: "$tomcatVersion"
274+
implementation group: 'org.apache.tomcat', name: 'tomcat-jasper', version: "$tomcatVersion"
275+
implementation group: 'org.apache.tomcat', name: 'tomcat-jasper-el', version: "$tomcatVersion"
276+
implementation group: 'org.apache.tomcat', name: 'tomcat-jsp-api', version: "$tomcatVersion"
183277

184278
testImplementation('io.github.glytching:junit-extensions:2.6.0')
185279
testImplementation('org.hamcrest:hamcrest-integration:1.3')
186280
testImplementation(platform('org.junit:junit-bom:6.0.1'))
187281
testImplementation('org.junit.jupiter:junit-jupiter')
282+
283+
// JavaFX per-platform natives are wired up earlier via addJavafx(...).
188284
}
189285

190286
test {

docs/source/development/index.rst

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,36 @@ The following line in your .zshrc or .bashrc on Mac makes starting IntelliJ as a
1414
1515
alias intellij="sudo ~/Applications/IntelliJ\ IDEA\ Ultimate.app/Contents/MacOS/idea"
1616
17+
Building for Different Platforms
18+
---------------------------------
19+
20+
By default, the universal JAR includes JavaFX native libraries for:
21+
22+
- **Windows**: x86-64
23+
- **Linux**: x86-64
24+
- **macOS**: ARM64 (Apple Silicon)
25+
26+
If you need to build for a different architecture (e.g., ARM64 Linux or Intel Mac), you can modify ``build.gradle``:
27+
28+
1. Find the ``addJavafx`` calls near line 85:
29+
30+
.. code:: groovy
31+
32+
addJavafx('win', 'javafxWin')
33+
addJavafx('linux', 'javafxLinux')
34+
addJavafx('mac-aarch64', 'javafxMacAarch64')
35+
36+
2. Change the classifier to match your platform:
37+
38+
- **Intel Mac**: ``'mac'`` instead of ``'mac-aarch64'``
39+
- **ARM Linux**: ``'linux-aarch64'`` instead of ``'linux'``
40+
41+
3. Update the corresponding configuration name in the ``shadowJar`` configurations list (around line 109).
42+
43+
4. Update the ``verifyShadowJarNatives`` task (around line 120) to check for your platform's native library.
44+
45+
Available JavaFX classifiers: ``win``, ``linux``, ``linux-aarch64``, ``mac``, ``mac-aarch64``
46+
1747
General Design
1848
--------------
1949

docs/source/overview.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ONB-Classic is a fork of the OpenNetBoot project that has been used at Palantir
66
Availability
77
------------
88

9-
Releases are currently put on `Github <PUBLIC_URL_NEEDED>`_
9+
Releases are currently put on `Github <https://github.com/palantir/onb-classic/releases>`_
1010

1111
Release Schedule
1212
----------------

scripts/publish.sh

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)