Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .github/workflows/dist-win.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Build Windows MSI

on:
workflow_dispatch:
inputs:
ref:
description: "Branch or tag to build (defaults to the workflow caller's ref)"
required: false
default: ""

permissions:
contents: read

concurrency:
group: dist-win-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: windows-latest

steps:
- name: Harden Runner
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
with:
egress-policy: audit

- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.ref || github.ref }}

- name: Set up JDK 21 (x64)
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
with:
java-version: 21
distribution: 'temurin'
architecture: x64
cache: maven

- name: Set up Maven
uses: stCarolas/setup-maven@12eb41b233df95d49b0c11fc1b5bc8312e5d4ce0 # v5.1
with:
maven-version: 3.9.14

- name: Verify build prerequisites
shell: bash
run: |
set -e
echo "JDK: $(java -version 2>&1 | head -n1)"
echo "jpackage: $("$JAVA_HOME/bin/jpackage" --version)"
echo "WiX: $(where light.exe 2>/dev/null || echo MISSING)"
echo "Magick: $(where magick.exe 2>/dev/null || where convert.exe 2>/dev/null || echo MISSING)"
echo "Maven: $(mvn --version | head -n1)"

- name: Build MSI
shell: bash
run: |
mvn --show-version --batch-mode --errors --no-transfer-progress \
-Pdist-win \
-Djdk.x86_64.home="$JAVA_HOME" \
clean package

- name: Upload MSI artifact
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: inception-msi-x86_64
path: inception/inception-dist-win/target/jpackage-x86_64/*.msi
if-no-files-found: error
171 changes: 171 additions & 0 deletions inception/inception-dist-win/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>de.tudarmstadt.ukp.inception.app</groupId>
<artifactId>inception-app</artifactId>
<version>41.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

<artifactId>inception-dist-win</artifactId>
<name>INCEpTION - App - Windows application</name>
<packaging>pom</packaging>

<dependencies>
<dependency>
<groupId>de.tudarmstadt.ukp.inception.app</groupId>
<artifactId>inception-app-webapp</artifactId>
<version>${project.version}</version>
<type>jar</type>
<classifier>lib</classifier>
</dependency>
</dependencies>

<profiles>
<profile>
<id>dist-win</id>

<properties>
<!-- Empty default so an unset 'jdk.x86_64.home' resolves to "" rather
than the literal '${…}'. Override in ~/.m2/settings.xml or via -D. -->
<jdk.x86_64.home></jdk.x86_64.home>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-dist-prerequisites</id>
<phase>validate</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireOS>
<family>windows</family>
<message>The 'dist-win' profile builds a Windows MSI installer and must be run on Windows. The build host also needs WiX Toolset (https://wixtoolset.org/) on PATH for jpackage to produce an MSI.</message>
</requireOS>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>stage-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/jpackage-input</outputDirectory>
<includeScope>runtime</includeScope>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
<execution>
<id>stage-provided-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/jpackage-input</outputDirectory>
<includeScope>provided</includeScope>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>parse-version</id>
<phase>initialize</phase>
<goals>
<goal>parse-version</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>create-ico</id>
<phase>prepare-package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>bash</executable>
<arguments>
<argument>${project.basedir}/src/main/scripts/create-ico.sh</argument>
<argument>${session.executionRootDirectory}/icon.png</argument>
<argument>${project.build.directory}/icon.ico</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>process-native-libs</id>
<phase>prepare-package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>bash</executable>
<arguments>
<argument>${project.basedir}/src/main/scripts/process-native-libs.sh</argument>
<argument>${project.build.directory}/jpackage-input</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>package-msi-x86_64</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>bash</executable>
<arguments>
<argument>${project.basedir}/src/main/scripts/package-msi.sh</argument>
<argument>x86_64</argument>
<argument>${jdk.x86_64.home}</argument>
<argument>${project.build.directory}/jpackage-input</argument>
<argument>${project.build.directory}/jpackage-x86_64</argument>
<argument>inception-app-webapp-${project.version}-lib.jar</argument>
<argument>de.tudarmstadt.ukp.inception.INCEpTION</argument>
<argument>${parsedVersion.majorVersion}.${parsedVersion.minorVersion}</argument>
<argument>${project.build.directory}/icon.ico</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
44 changes: 44 additions & 0 deletions inception/inception-dist-win/src/main/scripts/create-ico.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/sh
#
# Licensed to the Technische Universität Darmstadt under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The Technische Universität Darmstadt
# licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Generates a multi-resolution Windows .ico from a source PNG using
# ImageMagick. ImageMagick must be on PATH ('magick' from IM 7+, falling back
# to 'convert' from IM 6).

set -eu

SOURCE_PNG="$1"
OUTPUT_ICO="$2"

if [ ! -f "$SOURCE_PNG" ]; then
echo "ERROR: Source PNG not found at $SOURCE_PNG"
exit 1
fi

if command -v magick >/dev/null 2>&1; then
IM="magick"
elif command -v convert >/dev/null 2>&1; then
IM="convert"
else
echo "ERROR: ImageMagick not found on PATH (need 'magick' or 'convert'). Install from https://imagemagick.org/."
exit 1
fi

echo "Building Windows .ico from $SOURCE_PNG via $IM..."
$IM "$SOURCE_PNG" -define icon:auto-resize=256,128,64,48,32,16 "$OUTPUT_ICO"
echo "Wrote $OUTPUT_ICO"
111 changes: 111 additions & 0 deletions inception/inception-dist-win/src/main/scripts/package-msi.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/bin/sh
#
# Licensed to the Technische Universität Darmstadt under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The Technische Universität Darmstadt
# licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Builds a per-arch Windows MSI via jpackage. Falls back to JAVA_HOME when
# the native-arch JDK home is not configured; skips with a warning when
# building cross-arch without a configured JDK.
#
# Args (positional):
# 1: target arch (x86_64 | aarch64)
# 2: JDK home for target arch (may be empty -> resolve from JAVA_HOME or skip)
# 3: input dir (jpackage-input)
# 4: destination dir
# 5: main jar
# 6: main class
# 7: app version
# 8: icon path

set -eu

TARGET_ARCH="$1"
JDK_HOME="$2"
INPUT_DIR="$3"
DEST_DIR="$4"
MAIN_JAR="$5"
MAIN_CLASS="$6"
APP_VERSION="$7"
ICON="$8"

# Maven leaves unresolved property references as the literal "${name}" string;
# treat that as unset.
case "$JDK_HOME" in
'${'*'}') JDK_HOME='' ;;
esac

# Normalize host arch reported by uname/wmic to a canonical value.
HOST_ARCH=$(uname -m 2>/dev/null || echo "")
case "$HOST_ARCH" in
arm64|aarch64) HOST_ARCH=aarch64 ;;
x86_64|amd64) HOST_ARCH=x86_64 ;;
*)
# On native cmd.exe (no uname), fall back to env var.
case "${PROCESSOR_ARCHITECTURE:-}" in
AMD64) HOST_ARCH=x86_64 ;;
ARM64) HOST_ARCH=aarch64 ;;
esac
;;
esac

if [ -z "$JDK_HOME" ]; then
if [ "$TARGET_ARCH" = "$HOST_ARCH" ]; then
if [ -n "${JAVA_HOME:-}" ]; then
echo "No 'jdk.${TARGET_ARCH}.home' configured; falling back to JAVA_HOME=$JAVA_HOME (native arch)."
JDK_HOME="$JAVA_HOME"
else
echo "ERROR: No 'jdk.${TARGET_ARCH}.home' configured and JAVA_HOME is unset."
exit 1
fi
else
echo "WARNING: No 'jdk.${TARGET_ARCH}.home' configured. Skipping ${TARGET_ARCH} MSI build (cross-arch)."
exit 0
fi
fi

# jpackage on Windows is jpackage.exe; under Git Bash plain "jpackage" works too.
JPACKAGE="$JDK_HOME/bin/jpackage"
if [ ! -x "$JPACKAGE" ] && [ ! -x "$JPACKAGE.exe" ]; then
echo "ERROR: jpackage not found at $JPACKAGE(.exe)"
exit 1
fi

echo "Building ${TARGET_ARCH} MSI via $JPACKAGE..."

"$JPACKAGE" \
--type msi \
--name INCEpTION \
--app-version "$APP_VERSION" \
--input "$INPUT_DIR" \
--dest "$DEST_DIR" \
--main-jar "$MAIN_JAR" \
--main-class "$MAIN_CLASS" \
--java-options -Xmx4g \
--icon "$ICON" \
--win-dir-chooser \
--win-menu \
--win-shortcut

# Tag the produced MSI with the target arch so multiple builds can coexist.
for f in "$DEST_DIR"/*.msi; do
[ -e "$f" ] || continue
base=$(basename "$f" .msi)
case "$base" in
*-"$TARGET_ARCH") tagged="$f" ;;
*) tagged="$DEST_DIR/$base-$TARGET_ARCH.msi"; mv "$f" "$tagged" ;;
esac
echo "Wrote $tagged"
done
Loading
Loading