Convert build script to python
Some checks failed
system-test / waitForNative (push) Has been cancelled
system-test / buildMockserver (push) Has been cancelled
system-test / runSystemTestsLinux (map[name:core port:5076]) (push) Has been cancelled
system-test / runSystemTestsLinux (map[name:v1Migration port:5077]) (push) Has been cancelled
system-test / runSystemTestsWindows (push) Has been cancelled

This commit is contained in:
TheOtherP 2026-01-17 10:26:21 +01:00
parent dad346379c
commit 285adaaadf
9 changed files with 1499 additions and 307 deletions

2
.gitignore vendored
View File

@ -26,6 +26,8 @@ heapdump*
!/.idea/vcs.xml
!/.idea/misc.xml
misc/rsyncToServers.sh
misc/build-logs
misc/.build-release-state.json
/nzbhydra.yml
/results
other/wrapper/pyInstaller/windows/build

View File

@ -23,6 +23,7 @@
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.42/lombok-1.18.42.jar" />
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.42/lombok-1.18.42.jar" />
</processorPath>
<module name="mapping" />
</profile>
@ -50,6 +51,7 @@
<outputRelativeToContentRoot value="true" />
<processorPath useClasspath="false">
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.42/lombok-1.18.42.jar" />
<entry name="$MAVEN_REPOSITORY$/org/projectlombok/lombok/1.18.42/lombok-1.18.42.jar" />
</processorPath>
<module name="release-parser" />
</profile>

264
WINDOWS-VM-BUILD-SETUP.md Normal file
View File

@ -0,0 +1,264 @@
# Windows VM Setup for GraalVM Native Builds
This document describes how to set up a headless Windows VM on Linux for building Windows native executables using GraalVM.
## Why This Is Needed
GraalVM native-image doesn't support cross-compilation. To build Windows executables from Linux, you need a Windows environment. A headless VM with SSH access provides CLI-controllable builds.
## Prerequisites
- Linux host with KVM support (`grep -E 'vmx|svm' /proc/cpuinfo`)
- Windows ISO (Windows 10/11)
- VirtIO drivers ISO: https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/
## Step 1: Install QEMU/KVM
### Ubuntu/Debian
```bash
sudo apt install qemu-kvm libvirt-daemon-system virtinst virt-manager
sudo usermod -aG libvirt,kvm $USER
# Log out and back in for group changes
```
### Fedora
```bash
sudo dnf install @virtualization
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt $USER
```
### Arch
```bash
sudo pacman -S qemu-full libvirt virt-manager dnsmasq
sudo systemctl enable --now libvirtd
sudo usermod -aG libvirt $USER
```
## Step 2: Create Windows VM
```bash
# Create directory for VMs
mkdir -p ~/vms
# Create disk image (60GB, grows dynamically)
qemu-img create -f qcow2 ~/vms/windows-build.qcow2 60G
# Start installation
virt-install \
--name windows-build \
--ram 8192 \
--vcpus 4 \
--disk path=~/vms/windows-build.qcow2,format=qcow2,bus=virtio \
--cdrom /path/to/windows.iso \
--disk path=/path/to/virtio-win.iso,device=cdrom \
--os-variant win11 \
--network network=default,model=virtio \
--graphics spice
```
This opens a graphical installer. Complete the Windows installation.
**During installation**: Load VirtIO drivers from the second CD-ROM when Windows can't find the disk.
## Step 3: Windows VM Configuration
After Windows is installed, perform these steps inside the VM:
### Install VirtIO Drivers
- Open Device Manager
- Update any devices with missing drivers using the VirtIO CD-ROM
### Install OpenSSH Server
Open PowerShell as Administrator:
```powershell
# Install OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# Start and enable the service
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
# Configure firewall (usually automatic)
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
```
### Install Build Tools
1. **GraalVM Community Edition**
- Download from https://github.com/graalvm/graalvm-ce-builds/releases
- Extract to `C:\Program Files\graalvm`
- Set `JAVA_HOME` and add to `PATH`
2. **Visual Studio Build Tools**
- Download from https://visualstudio.microsoft.com/visual-cpp-build-tools/
- Install "Desktop development with C++" workload
- Required for native-image on Windows
3. **Maven**
- Download from https://maven.apache.org/download.cgi
- Extract and add `bin` to `PATH`
4. **Git** (optional, if syncing via git instead of rsync)
- Download from https://git-scm.com/download/win
### Configure Static IP (Recommended)
In Windows Network Settings, set a static IP like `192.168.122.100` to make SSH scripting easier.
### Set Up SSH Key Authentication
From your Linux host:
```bash
ssh-copy-id builder@192.168.122.100
```
## Step 4: VM Management Commands
```bash
# Start VM (headless)
virsh start windows-build
# Check running VMs
virsh list
# Get VM IP address
virsh domifaddr windows-build
# Shutdown gracefully
virsh shutdown windows-build
# Force stop
virsh destroy windows-build
# Create snapshot (recommended after setup)
virsh snapshot-create-as windows-build clean-setup "Fresh install with build tools"
# Restore snapshot
virsh snapshot-revert windows-build clean-setup
```
## Step 5: Build Script
Create `build-windows.sh` in the project root:
```bash
#!/bin/bash
set -e
VM_NAME="windows-build"
WIN_USER="builder"
WIN_HOST="192.168.122.100"
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
BUILD_DIR="C:\\Users\\$WIN_USER\\nzbhydra2"
echo "=== Windows Native Build ==="
# Start VM if not running
if ! virsh list --name | grep -q "^${VM_NAME}$"; then
echo "Starting Windows VM..."
virsh start "$VM_NAME"
echo "Waiting for VM to boot..."
sleep 60
fi
# Wait for SSH to be available
echo "Waiting for SSH..."
until ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no "$WIN_USER@$WIN_HOST" "echo ready" 2>/dev/null; do
sleep 5
done
echo "SSH is ready"
# Sync source code
echo "Syncing source code..."
rsync -avz --delete \
--exclude 'target/' \
--exclude '.git/' \
--exclude '.idea/' \
--exclude '*.iml' \
"$PROJECT_DIR/" \
"$WIN_USER@$WIN_HOST:nzbhydra2/"
# Run build
echo "Running build..."
ssh "$WIN_USER@$WIN_HOST" "cd nzbhydra2 && cmd /c buildCore.cmd"
# Copy artifact back
echo "Copying artifact..."
mkdir -p "$PROJECT_DIR/core/target"
scp "$WIN_USER@$WIN_HOST:nzbhydra2/core/target/core.exe" \
"$PROJECT_DIR/core/target/core-windows.exe"
echo "=== Build complete: core/target/core-windows.exe ==="
# Uncomment to shutdown VM after build:
# virsh shutdown "$VM_NAME"
```
Make it executable:
```bash
chmod +x build-windows.sh
```
## Usage
```bash
# One command to build Windows executable
./build-windows.sh
```
## Troubleshooting
### VM won't start
```bash
# Check for errors
virsh start windows-build 2>&1
# Check libvirt logs
sudo journalctl -u libvirtd
```
### Can't connect via SSH
```bash
# Check VM is running
virsh list
# Get IP address
virsh domifaddr windows-build
# Check if SSH port is open
nc -zv 192.168.122.100 22
```
### Build fails
SSH into the VM and run the build manually to see full output:
```bash
ssh builder@192.168.122.100
cd nzbhydra2
cmd /c buildCore.cmd
```
### Performance issues
- Ensure KVM is enabled: `lsmod | grep kvm`
- Increase RAM/CPU in VM settings
- Use VirtIO drivers for disk and network
## Notes
- The Windows VM requires a valid Windows license
- First boot after shutdown takes longer (Windows updates, etc.)
- Consider keeping the VM running during development sessions
- Snapshot the VM after successful setup to enable easy recovery

View File

@ -1,291 +0,0 @@
#@formatter:off
function Exec([scriptblock]$cmd, [string]$errorMessage = "Error executing command: " + $cmd) {
& $cmd
if ($LastExitCode -ne 0) {
git reset --hard
throw $errorMessage
}
}
$ErrorActionPreference = 'Stop'
$version = $args[0]
$nextVersion = $args[1]
$dryRun = $args[2]
if (!$version) {
Write-Error "Version is required"
exit 1
}
if (!$nextVersion) {
Write-Error "Next version is required"
exit 1
}
if ($version -eq $nextVersion) {
Write-Error "next version $nextVersion must be different from current version $version"
exit 1
}
$env:githubReleasesUrl = "https://api.github.com/repos/theotherp/nzbhydra2/releases"
if ($dryRun -ne "true" -and $dryRun -ne "false") {
Write-Error "Dry run must be true or false"
exit 1
}
$dryRun = [System.Convert]::ToBoolean($dryRun)
if ($dryRun) {
Write-Host "Dry run is enabled"
} else {
Write-Host "Dry run is disabled"
}
if (Test-Path "discordtoken.txt") {
$discordToken = Get-Content "discordtoken.txt"
$env:DISCORD_TOKEN = $discordToken
Write-Host "Discord token is set"
}
if (Test-Path "githubtoken.txt") {
$githubToken = Get-Content "githubtoken.txt"
$env:GITHUB_TOKEN = $githubToken
Write-Host "Github token is set"
$response = Invoke-WebRequest -Uri https://api.github.com -Method Head -Headers @{"Authorization" = "token $githubToken"}
if ($response.StatusCode -eq 200) {
Write-Host "GitHub token seems to be valid - HTTP status code is 200 OK"
} else {
Write-Error "GitHub token seems to be invalid - HTTP status code is $($response.StatusCode)"
exit 1
}
}
if ($discordToken -eq $null) {
Write-Error "Discord token is required"
exit 1
}
if ($githubToken -eq $null) {
Write-Error "Github token is required"
exit 1
}
if (!(Test-Path "readme.md")) {
Write-Error "Readme.md is required"
exit 1
}
if ((git status --porcelain) -ne $null) {
Write-Error "Git has untracked or changed files"
exit 1
}
else {
Write-Host "Git is clean"
}
$dockerInfo = wsl -d Ubuntu -- sh -c "docker info"
if (!$dockerInfo -contains "Docker Root Dir") {
Write-Error "Docker is not running in WSL"
exit 1
}
$env:Path = "$HOME\.jdks\openjdk-21.0.2\bin\;"+$env:Path
$env:JAVA_HOME = "$HOME\.jdks\openjdk-21.0.2"
Write-Host "Setting release version"
exec { mvn -q -B versions:set `-DnewVersion="$version" }
if (-not $?) {
Write-Error "Setting release version failed"
git reset --hard
exit 1
}
Write-Host "Checking preconditions"
exec { mvn -q -B org.nzbhydra:github-release-plugin:3.0.0:precheck }
if (-not $?) {
Write-Error "Preconditions failed"
git reset --hard
exit 1
}
Write-Host "Generating changelog"
exec { mvn -q -B org.nzbhydra:github-release-plugin:3.0.0:generate-changelog }
if (-not $?) {
Write-Error "Changing log generation failed"
git reset --hard
exit 1
}
Write-Host "Generating wrapper hashes"
exec { mvn -q -B org.nzbhydra:github-release-plugin:3.0.0:generate-wrapper-hashes }
if (-not $?) {
Write-Error "Wrapper hash generation failed"
git reset --hard
exit 1
}
Write-Host "Making versions effective"
exec { mvn -q -B versions:commit }
if (-not $?) {
Write-Error "Making versions effective failed"
git reset --hard
exit 1
}
Write-Host "Building core jar"
exec { mvn -q -pl org.nzbhydra:nzbhydra2,org.nzbhydra:shared,org.nzbhydra:mapping,org.nzbhydra:release-parser,org.nzbhydra:core clean install -B -T 1C `-DskipTests=true}
erase .\releases\generic-release\include\*.jar
copy .\core\target\*-exec.jar .\releases\generic-release\include\
if (-not $?) {
Write-Error "Clean install of core failed"
git reset --hard
exit 1
}
$genericVersion = java -jar releases/generic-release/include/core-$version-exec.jar -version
if ($genericVersion -ne $version) {
Write-Error "Generic version $version expected but is $genericVersion"
exit 1
}
Write-Host "Building windows executable"
try {
.\buildCore.cmd
copy .\core\target\core.exe .\releases\windows-release\include\
copy .\core\target\*.dll .\releases\windows-release\include\
} catch {
exit 1
}
$windowsVersion = releases/windows-release/include/core.exe -version
if ($windowsVersion -ne $version) {
Write-Error "Windows version $version expected but is $windowsVersion"
exit 1
}
Write-Host "Building linux amd64 executables"
wsl -d Ubuntu -- sh -c ./misc/buildLinuxCore/buildBoth.sh
$linuxAmd64Version = wsl -d Ubuntu releases/linux-amd64-release/include/executables/core -version
if ($linuxAmd64Version -ne $version) {
Write-Error "Linux amd64 version $version expected but is $linuxAmd64Version"
exit 1
}
#We must ask the build machine because we can't run the binary locally
$linuxArm64Version = wsl -d Ubuntu -- sh -c "ssh -i ~/.ssh/oraclecloud.key build@141.147.54.141 /home/build/nzbhydra2/core/target/core -version"
if ($linuxArm64Version -ne $version) {
Write-Error "Linux arm64 version $version expected but is $linuxArm64Version"
exit 1
}
Write-Host "All required files exist and versions match"
Write-Host "Building releases ***********************************************************************"
exec { mvn -q -pl org.nzbhydra:windows-release,org.nzbhydra:generic-release,org.nzbhydra:linux-amd64-release,org.nzbhydra:linux-arm64-release clean install -T 1C `-DskipTests=true}
#We need to commit and push the source code now so that it's packaged in the release
if ($dryRun) {
Write-Host "Committing (not really, just dry run) ***********************************************************************"
} else {
Write-Host "Committing ***********************************************************************"
git commit -am "Update to $version"
if (-not $?) {
Write-Error "Commit failed"
git reset --hard
exit 1
}
}
if ($dryRun) {
Write-Host "Tagging (not really, just dry run) ***********************************************************************"
} else {
Write-Host "Tagging ***********************************************************************"
git tag -a v$version -m v$version
if (-not $?) {
Write-Error "Tagging failed"
git reset --hard
exit 1
}
}
if ($dryRun) {
Write-Host "Pushing (not really, just dry run) ***********************************************************************"
} else {
Write-Host "Pushing ***********************************************************************"
git push
git push origin v$version
if (-not $?) {
Write-Error "Pushing failed"
git reset --hard
exit 1
}
}
if ($dryRun) {
Write-Host "Releasing to github (not really, just dry run) ***********************************************************************"
exec { mvn -B org.nzbhydra:github-release-plugin:3.0.0:release `-DdryRun }
} else {
Write-Host "Releasing to github ***********************************************************************"
exec { mvn -B org.nzbhydra:github-release-plugin:3.0.0:release }
}
if (-not $?) {
Write-Error "Releasing to github failed"
exit 1
}
if ($dryRun) {
Write-Host "Publishing to discord (not really, just dry run) ***********************************************************************"
exec { java -jar other/discord-releaser/target/discordreleaser-jar-with-dependencies.jar core/src/main/resources/changelog.yaml $version discordtoken.txt true }
} else {
Write-Host "Publishing to discord ***********************************************************************"
exec { java -jar other/discord-releaser/target/discordreleaser-jar-with-dependencies.jar core/src/main/resources/changelog.yaml $version discordtoken.txt false }
}
if (-not $?) {
Write-Error "Publishing to discord failed"
Read-Host -Prompt "Press enter to continue"
}
Write-Host "Setting new snapshot version"
exec { mvn -B versions:set `-DnewVersion="$nextVersion"-SNAPSHOT }
if (-not $?) {
Write-Error "Setting new snapshot version failed"
git reset --hard
exit 1
}
Write-Host "Making snapshot version effective"
exec { mvn -B versions:commit }
if (-not $?) {
Write-Error "Making snapshot version effective failed"
git reset --hard
exit 1
}
if ($dryRun) {
Write-Host "Committing update to $nextVersion-SNAPSHOT (not really, just dry run) ***********************************************************************"
} else {
Write-Host "Committing ***********************************************************************"
git commit -am "Update to $nextVersion-SNAPSHOT"
if (-not $?) {
Write-Error "Commit failed"
git reset --hard
exit 1
}
}
Write-Host "Done"

View File

@ -1,19 +1,29 @@
#!/bin/bash
set -e # Exit on any error
# Prepares and runs the docker container to build the core executable
if [[ ! -d "${PWD}/core" ]] ; then
echo "${PWD}/core not found - you must be in the project main folder"
exit
exit 1
fi
echo Removing old amd64 executable
rm -f releases/linux-amd64-release/include/executables/core
echo Syncing with build directory
rsync -ru --delete --exclude "target" --exclude "bower_components" --exclude "node_modules" --exclude ".git" --exclude ".idea" --exclude "results" --exclude "*.db" --exclude "venv*" ${PWD}/ ~/nzbhydra2/
echo Running build script using docker
docker run -v ~/nzbhydra2/:/nzbhydra2:rw -v ~/.m2/repository:/home/sist/.m2/repository:rw --rm hydrabuild:latest
docker run -v ~/nzbhydra2/:/nzbhydra2:rw -v ~/.m2/repository:~/.m2/repository:rw --rm hydrabuild:latest
if [[ ! -f ~/nzbhydra2/core/target/core ]] ; then
echo "core executable does not exist"
else
cp ~/nzbhydra2/core/target/core ${PWD}/core/target/
cp ~/nzbhydra2/core/target/core ${PWD}/releases/linux-amd64-release/include/executables/
echo "ERROR: core executable does not exist after build"
exit 1
fi
echo Copying executable to target directories
cp ~/nzbhydra2/core/target/core ${PWD}/core/target/
cp ~/nzbhydra2/core/target/core ${PWD}/releases/linux-amd64-release/include/executables/
echo "amd64 build completed successfully"

View File

@ -1,17 +1,23 @@
#!/bin/bash
set -e # Exit on any error
# Prepares and runs the docker container to build the core executable
if [[ ! -d "${PWD}/core" ]] ; then
echo "${PWD}/core not found - you must be in the project main folder"
exit
exit 1
fi
echo Removing old arm64 executable
rm -f releases/linux-arm64-release/include/executables/core
echo Syncing with remote server
rsync -e "ssh -i ~/.ssh/oraclecloud.key" -rvu --exclude "target" --exclude "executables/core" --exclude "bower_components" --exclude "node_modules" --exclude ".git" --exclude ".idea" --exclude "results" --exclude "*.db" --exclude "*.zip" --exclude "*.jar" --exclude "*.exe" --exclude "venv*" ${PWD}/ build@141.147.54.141:~/nzbhydra2/ --delete
echo Running build script on remote server
ssh -i ~/.ssh/oraclecloud.key build@141.147.54.141 /home/build/nzbhydra2/misc/buildLinuxCore/arm64/runOnRemoteMachine.sh
echo Writing file from remote server to ${PWD}/releases/linux-arm64-release/include/executables/
scp -i ~/.ssh/oraclecloud.key build@141.147.54.141:/home/build/nzbhydra2/core/target/core ${PWD}/releases/linux-arm64-release/include/executables/
echo Copying file from remote server to ${PWD}/releases/linux-arm64-release/include/executables/
scp -i ~/.ssh/oraclecloud.key build@141.147.54.141:/home/build/nzbhydra2/core/target/core ${PWD}/releases/linux-arm64-release/include/executables/
echo "arm64 build completed successfully"

View File

@ -1,7 +0,0 @@
#!/bin/bash
rm releases/linux-amd64-release/include/executables/core
rm releases/linux-arm64-release/include/executables/core
misc/buildLinuxCore/amd64/buildLinuxCore.sh &
misc/buildLinuxCore/arm64/buildLinuxCore.sh &
wait

1203
misc/build_and_release.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
# Dependencies for build_and_release.py
click>=8.0.0
rich>=13.0.0