Skip to content

Fix Docker building (and also build for forks) #14290

Fix Docker building (and also build for forks)

Fix Docker building (and also build for forks) #14290

Workflow file for this run

name: Binaries
on:
push:
branches:
- main
- main-release
paths-ignore:
- 'docs/**'
- 'src/test/**'
- 'README.md'
tags:
- '*'
pull_request:
types:
- opened
- synchronize
- reopened
- labeled
merge_group:
workflow_dispatch:
inputs:
jvmDistribution:
description: "JDK distribution (setup-java)"
type: choice
default: corretto
options:
# These are the distributions listed at https://github.com/actions/setup-java/blob/main/README.md#supported-distributions
- adopt
- adopt-openj9
- corretto
- dragonwell
- graalvm
- jetbrains
- liberica
- microsoft
- oracle
- sapmachine
- semeru
- temurin
- zulu
jvmVendor:
description: "JDK vendor (gradle toolchain)"
type: choice
default: AMAZON
options:
# These are the vendors listed at https://docs.gradle.org/current/javadoc/org/gradle/jvm/toolchain/JvmVendorSpec.html
- ADOPTIUM
- ADOPTOPENJDK
- AMAZON
- APPLE
- AZUL
- BELLSOFT
- GRAAL_VM
- HEWLETT_PACKARD
- IBM
- JETBRAINS
- MICROSOFT
- ORACLE
- SAP
- TENCENT
useEaJdk:
description: "Use early-access JDK and JavaFX"
type: boolean
required: false
default: false
jdkVersion:
description: "JDK EA version (used for gradle)"
type: number
required: false
default: 26
jdkVersionFlavour:
description: "JDK EA flavour (used for oracle-actions/setup-java)"
type: choice
required: false
default: stable
options:
# use the next JDK
- stable
# use the next-next JDK
- latest
javafxVersion:
description: "JavaFX EA"
type: string
required: false
default: "26-ea+22"
notarization:
description: "Notarize macOS DMG and PKG"
type: boolean
required: false
default: false
upload:
description: "Upload to builds.jabref.org"
type: boolean
required: false
default: false
upload-as-artifact:
description: "Upload to GitHub artifacts store"
type: boolean
required: false
default: true
permissions:
actions: write
contents: read
pull-requests: write
env:
GRADLE_OPTS: -Xmx4g -Dorg.gradle.vfs.watch=false
JAVA_OPTS: -Xmx4g
# API keys
AstrophysicsDataSystemAPIKey: ${{ secrets.AstrophysicsDataSystemAPIKey }}
BiodiversityHeritageApiKey: ${{ secrets.BiodiversityHeritageApiKey}}
IEEEAPIKey: ${{ secrets.IEEEAPIKey }}
SpringerNatureAPIKey: ${{ secrets.SpringerNatureAPIKey }}
concurrency:
group: "${{ github.workflow }}-${{ github.head_ref || github.ref }}-${{ github.event_name }}-${{ github.event.inputs.useEaJdk }}-${{ github.event.inputs.jdkVersion }}-${{ github.event.inputs.jdkVersionFlavour }}-${{ github.event.inputs.javafxVersion }}"
cancel-in-progress: true
jobs:
conditions:
# Dependency updates should only run in the main repo
if: ${{ github.repository == 'JabRef/jabref' || github.actor != 'dependabot[bot]' || github.ref_name != 'main' }}
runs-on: ubuntu-slim
outputs:
upload-to-builds-jabref-org: ${{ steps.binary.outputs.upload-to-builds-jabref-org }}
secretspresent: ${{ steps.binary.outputs.secretspresent }}
tagbuild: ${{ steps.binary.outputs.tagbuild }}
# required to avoid obsolete builds in case of labels != "dev: binaries"
should-build: ${{ steps.binary.outputs.should-build }}
should-jbundle: ${{ steps.binary.outputs.should-jbundle }}
should-notarize: ${{ steps.binary.outputs.should-notarize }}
jvmDistribution: ${{ steps.binary.outputs.jvmDistribution }}
useEaJdk: ${{ steps.binary.outputs.useEaJdk }}
jdkVersion: ${{ steps.binary.outputs.jdkVersion }}
jdkVersionFlavour: ${{ steps.binary.outputs.jdkVersionFlavour }}
javafxVersion: ${{ steps.binary.outputs.javafxVersion }}
steps:
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: jq
version: 1.0
- name: Determine conditions
id: binary
shell: bash
env:
BUILDJABREFPRIVATEKEY: ${{ secrets.buildJabRefPrivateKey }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVENT_NAME: ${{ github.event_name }}
LABEL_NAME: ${{ github.event.label.name }}
REPO_OWNER: ${{ github.repository_owner }}
run: |
set -euo pipefail
set -x
PS4='+ ${LINENO}: '
if [[ "$EVENT_NAME" != "labeled" || "$LABEL_NAME" == "automerge" || "$LABEL_NAME" == "dev: binaries" ]]; then
echo "📦 build enabled"
echo "📦 build enabled" >> $GITHUB_STEP_SUMMARY
echo "should-build=true" >> "$GITHUB_OUTPUT"
else
echo "⊘ build should be skipped"
echo "⊘ build should be skipped" >> $GITHUB_STEP_SUMMARY
echo "should-build=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ "${{ github.event.inputs.useEaJdk || 'false' }}" == "true" ]]; then
echo "🚀 JDK EA build enabled"
echo "🚀 JDK EA build enabled" >> "$GITHUB_STEP_SUMMARY"
echo "JDK EA version: ${{ github.event.inputs.jdkVersion }}"
echo "JDK EA version: ${{ github.event.inputs.jdkVersion }}" >> "$GITHUB_STEP_SUMMARY"
echo "JDK EA flavour: ${{ github.event.inputs.jdkVersionFlavour }}"
echo "JDK EA flavour: ${{ github.event.inputs.jdkVersionFlavour }}" >> "$GITHUB_STEP_SUMMARY"
echo "JavaFX version: ${{ github.event.inputs.javafxVersion }}"
echo "JavaFX version: ${{ github.event.inputs.javafxVersion }}" >> "$GITHUB_STEP_SUMMARY"
echo "useEaJdk=true" >> "$GITHUB_OUTPUT"
else
echo "🛡️ JDK stable version used"
echo "🛡️ JDK stable version used" >> "$GITHUB_STEP_SUMMARY"
echo "useEaJdk=false" >> "$GITHUB_OUTPUT"
echo "JVM vendor: ${{ github.event.inputs.jvmVendor || '(unset)' }}"
echo "JVM vendor: ${{ github.event.inputs.jvmVendor || '(unset)' }}" >> "$GITHUB_STEP_SUMMARY"
fi
# The distribution to use at setup-java
echo "JVM distribution: ${{ github.event.inputs.jvmDistribution || 'corretto' }}"
echo "jvmDistribution=${{ github.event.inputs.jvmDistribution || 'corretto' }}" >> "$GITHUB_OUTPUT"
# Enable testing of EA JDKs later even if not triggered by workflow dispatch.
# One needs to set "useEaJdk=true" above even at the stable case to enable this.
echo "jdkVersion=${{ github.event.inputs.jdkVersion || '26' }}" >> "$GITHUB_OUTPUT"
echo "jdkVersionFlavour=${{ github.event.inputs.jdkVersionFlavour || 'stable' }}" >> "$GITHUB_OUTPUT"
echo "javafxVersion=${{ github.event.inputs.javafxVersion || '26-ea+22' }}" >> "$GITHUB_OUTPUT"
if [ -z "$BUILDJABREFPRIVATEKEY" ]; then
echo "⊘ Secret BUILDJABREFPRIVATEKEY not present – skipping upload"
echo "⊘ Secret BUILDJABREFPRIVATEKEY not present – skipping upload"
echo "upload-to-builds-jabref-org=false" >> "$GITHUB_OUTPUT"
echo "secretspresent=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "secretspresent=true" >> "$GITHUB_OUTPUT"
if [[ "$GITHUB_REF" == refs/heads/gh-readonly-queue* ]]; then
echo "⊘ merge queue – skipping upload"
echo "⊘ merge queue – skipping upload" >> $GITHUB_STEP_SUMMARY
echo "upload-to-builds-jabref-org=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
echo "🏷️ tag build" >> $GITHUB_STEP_SUMMARY
echo "tagbuild=true" >> "$GITHUB_OUTPUT"
echo "🧰 jbundle build" >> $GITHUB_STEP_SUMMARY
echo "should-jbundle=true" >> "$GITHUB_OUTPUT"
else
echo "⊘ no tag bulid" >> $GITHUB_STEP_SUMMARY
echo "tagbuild=false" >> "$GITHUB_OUTPUT"
fi
if [[ "${GITHUB_REF}" == refs/tags/* ]] || [[ "${GITHUB_REF}" == "refs/heads/main-release" ]] || [[ "${{ inputs.notarization }}" == "true" ]]; then
# This workflow runs on ubuntu-latest even for notarization for macOS; need to check later if really on macOS
echo "🧾 macOS notarization"
echo "🧾 macOS notarization" >> $GITHUB_STEP_SUMMARY
echo "should-notarize=true" >> "$GITHUB_OUTPUT"
if [[ "${GITHUB_REF}" == refs/tags/* || ( "${{ github.event_name }}" == "push" && ("${{ github.ref_name }}" == "main" || "${{ github.ref_name }}" == "main-release") ) ]]; then
echo "☁️ will upload"
echo "☁️ will upload" >> $GITHUB_STEP_SUMMARY
echo "upload-to-builds-jabref-org=true" >> "$GITHUB_OUTPUT"
exit 0;
fi;
echo "☁️ Non-PR event – will upload: ${{ github.event.inputs.upload || 'false' }}"
echo "☁️ Non-PR event – will upload: ${{ github.event.inputs.upload || 'false' }}" >> $GITHUB_STEP_SUMMARY
echo "upload-to-builds-jabref-org=${{ github.event.inputs.upload || 'false' }}" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "⊘ no macOS notarization"
echo "⊘ no macOS notarization" >> $GITHUB_STEP_SUMMARY
echo "should-notarize=false" >> "$GITHUB_OUTPUT"
if [[ "${{ github.event_name }}" == "push" ]]; then
if [[ "${{ github.ref_name }}" == "main" ]]; then
echo "☁️ Push to \`main\` – will upload"
echo "☁️ Push to \`main\` – will upload" >> $GITHUB_STEP_SUMMARY
echo "upload-to-builds-jabref-org=true" >> "$GITHUB_OUTPUT"
echo "🧰 jbundle build" >> $GITHUB_STEP_SUMMARY
echo "should-jbundle=true" >> "$GITHUB_OUTPUT"
exit 0
fi;
echo "⊘ Push to some branch not main – skipping upload"
echo "⊘ Push to some branch not main – skipping upload" >> $GITHUB_STEP_SUMMARY
echo "upload-to-builds-jabref-org=false" >> "$GITHUB_OUTPUT"
echo "🚫🧰 no jbundle build" >> $GITHUB_STEP_SUMMARY
echo "should-jbundle=false" >> "$GITHUB_OUTPUT"
exit 0
fi;
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "☁️? Dispatch event – will upload: ${{ github.event.inputs.upload || 'false' }}"
echo "☁️= Dispatch event – will upload: ${{ github.event.inputs.upload || 'false' }}" >> $GITHUB_STEP_SUMMARY
echo "upload-to-builds-jabref-org=${{ github.event.inputs.upload || 'false' }}" >> "$GITHUB_OUTPUT"
echo "should-jbundle=${{ github.event.inputs.upload || 'false' }}" >> "$GITHUB_OUTPUT"
exit 0
fi
LABELS=$(gh api repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels --jq '.[].name')
if echo "$LABELS" | grep -q "^dev: binaries$"; then
echo "☁️ Label 'dev: binaries' found – will upload"
echo "☁️ Label 'dev: binaries' found – will upload" >> $GITHUB_STEP_SUMMARY
echo "upload-to-builds-jabref-org=true" >> "$GITHUB_OUTPUT"
echo "🧰 jbundle build" >> $GITHUB_STEP_SUMMARY
echo "should-jbundle=true" >> "$GITHUB_OUTPUT"
else
echo "⊘ Label 'dev: binaries' not found – skipping upload"
echo "⊘ Label 'dev: binaries' not found – skipping upload" >> $GITHUB_STEP_SUMMARY
echo "upload-to-builds-jabref-org=false" >> "$GITHUB_OUTPUT"
echo "🚫🧰 no jbundle build" >> $GITHUB_STEP_SUMMARY
echo "should-jbundle=false" >> "$GITHUB_OUTPUT"
fi
disk-space-check:
needs: conditions
runs-on: ubuntu-slim
outputs:
available: ${{ steps.diskspace.outputs.available }}
steps:
- name: No upload
if: needs.conditions.outputs.upload-to-builds-jabref-org == 'false'
shell: bash
run: |
echo "⊘ no upload – skipping upload"
echo "⊘ no upload – skipping upload" >> $GITHUB_STEP_SUMMARY
echo "available=false" >> "$GITHUB_OUTPUT"
- name: Setup SSH key
if: needs.conditions.outputs.upload-to-builds-jabref-org == 'true'
run: |
echo "${{ secrets.buildJabRefPrivateKey }}" > sshkey
chmod 600 sshkey
- name: Check disk space on builds.jabref.org
if: needs.conditions.outputs.upload-to-builds-jabref-org == 'true'
id: diskspace
shell: bash
run: |
PR_NUMBER="${{ github.event.pull_request.number }}"
if [[ -z "$PR_NUMBER" ]]; then
echo "☁️ Not a pull request event – skipping disk space check – will upload"
echo "☁️ Not a pull request event – skipping disk space check – will upload" >> $GITHUB_STEP_SUMMARY
echo "available=true" >> "$GITHUB_OUTPUT"
exit 0
fi
TARGET="/var/www/builds.jabref.org/www/pull-$PR_NUMBER"
SSH_OPTS="-p 9922 -i sshkey -o StrictHostKeyChecking=no"
HOST="jrrsync@build-upload.jabref.org"
if ssh $SSH_OPTS "$HOST" "test -d '$TARGET'"; then
echo "☁️ Target exists: $TARGET - will upload"
echo "☁️ Target exists: $TARGET - will upload" >> $GITHUB_STEP_SUMMARY
echo "available=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "🤔 Target does not exist: $TARGET"
echo "🤔 Target does not exist: $TARGET" >> $GITHUB_STEP_SUMMARY
USAGE=$(ssh -p 9922 -i sshkey -o StrictHostKeyChecking=no jrrsync@build-upload.jabref.org \
"df --output=pcent /var/www/builds.jabref.org | tail -n1 | tr -dc '0-9'")
echo "Remote usage: ${USAGE}%"
echo "Remote usage: ${USAGE}%" >> $GITHUB_STEP_SUMMARY
if [ "$USAGE" -lt 80 ]; then
echo "☁️ enough disk space available – will upload"
echo "☁️ enough disk space available – will upload" >> $GITHUB_STEP_SUMMARY
echo "available=true" >> "$GITHUB_OUTPUT"
else
echo "⛔ not enough disk space – skipping upload"
echo "⛔ not enough disk space – skipping upload" >> $GITHUB_STEP_SUMMARY
echo "available=false" >> "$GITHUB_OUTPUT"
fi
compute-matrix:
needs: conditions
runs-on: ubuntu-slim
outputs:
matrix: ${{ steps.set.outputs.matrix }}
steps:
- id: set
name: Compute Matrix
shell: bash
env:
SHOULD_NOTARIZE: ${{ needs.conditions.outputs.should-notarize }}
run: |
# if you change the os version rename all other occurrences
# ./gradlew on Windows is because of https://github.com/gradle/gradle/pull/34227
MATRIX_JSON='{
"include": [
{
"os": "ubuntu-22.04",
"displayName": "linux-amd64",
"gradleCommand": "gradle",
"archivePortable": "tar -c -C jabgui/build/packages/ubuntu-22.04 JabRef | pigz --rsyncable > jabgui/build/packages/ubuntu-22.04/JabRef-portable_linux.tar.gz && rm -R jabgui/build/packages/ubuntu-22.04/JabRef",
"archivePortableJabKit": "tar -c -C jabkit/build/packages/ubuntu-22.04 jabkit | pigz --rsyncable > jabkit/build/packages/ubuntu-22.04/jabkit-portable_linux.tar.gz && rm -R jabkit/build/packages/ubuntu-22.04/jabkit",
"archivePortableJabLS": "tar -c -C jabls-cli/build/packages/ubuntu-22.04 jabls | pigz --rsyncable > jabls-cli/build/packages/ubuntu-22.04/jabls-portable_linux.tar.gz && rm -R jabls-cli/build/packages/ubuntu-22.04/jabls",
"suffix": "",
"archForDebianRepack": "_amd64"
},
{
"os": "ubuntu-22.04-arm",
"displayName": "linux-arm",
"gradleCommand": "gradle",
"archivePortable": "tar -c -C jabgui/build/packages/ubuntu-22.04-arm JabRef | pigz --rsyncable > jabgui/build/packages/ubuntu-22.04-arm/JabRef-portable_linux_arm64.tar.gz && rm -R jabgui/build/packages/ubuntu-22.04-arm/JabRef",
"archivePortableJabKit": "tar -c -C jabkit/build/packages/ubuntu-22.04-arm jabkit | pigz --rsyncable > jabkit/build/packages/ubuntu-22.04-arm/jabkit-portable_linux_arm64.tar.gz && rm -R jabkit/build/packages/ubuntu-22.04-arm/jabkit",
"archivePortableJabLS": "tar -c -C jabls-cli/build/packages/ubuntu-22.04-arm jabls | pigz --rsyncable > jabls-cli/build/packages/ubuntu-22.04-arm/jabls-portable_linux_arm64.tar.gz && rm -R jabls-cli/build/packages/ubuntu-22.04-arm/jabls",
"suffix": "_arm64",
"archForDebianRepack": "_arm64"
},
{
"os": "windows-latest",
"displayName": "windows-amd64",
"gradleCommand": "./gradlew",
"archivePortable": "7z a -r jabgui/build/packages/windows-latest/JabRef-portable_windows.zip ./jabgui/build/packages/windows-latest/JabRef && rm -R jabgui/build/packages/windows-latest/JabRef",
"archivePortableJabKit": "7z a -r jabkit/build/packages/windows-latest/jabkit-portable_windows.zip ./jabkit/build/packages/windows-latest/jabkit && rm -R jabkit/build/packages/windows-latest/jabkit",
"archivePortableJabLS": "7z a -r jabls-cli/build/packages/windows-latest/jabls-portable_windows.zip ./jabls-cli/build/packages/windows-latest/jabls && rm -R jabls-cli/build/packages/windows-latest/jabls",
"suffix": "",
"archForDebianRepack": ""
},
{
"os": "macos-15-intel",
"displayName": "macOS-intel",
"gradleCommand": "./gradlew",
"archivePortable": "7z a -r jabgui/build/packages/macos-15-intel/JabRef-portable_macos-intel.zip ./jabgui/build/packages/macos-15-intel/JabRef.app && rm -R jabgui/build/packages/macos-15-intel/JabRef.app",
"archivePortableJabKit": "7z a -r jabkit/build/packages/macos-15-intel/jabkit-portable_macos-intel.zip ./jabkit/build/packages/macos-15-intel/jabkit.app && rm -R jabkit/build/packages/macos-15-intel/jabkit.app",
"archivePortableJabLS": "7z a -r jabls-cli/build/packages/macos-15-intel/jabls-portable_macos-intel.zip ./jabls-cli/build/packages/macos-15-intel/jabls.app && rm -R jabls-cli/build/packages/macos-15-intel/jabls.app",
"suffix": "_intel",
"archForDebianRepack": ""
},
{
"os": "macos-15",
"displayName": "macOS-silicon",
"gradleCommand": "./gradlew",
"archivePortable": "7z a -r jabgui/build/packages/macos-15/JabRef-portable_macos-silicon.zip ./jabgui/build/packages/macos-15/JabRef.app && rm -R jabgui/build/packages/macos-15/JabRef.app",
"archivePortableJabKit": "7z a -r jabkit/build/packages/macos-15/jabkit-portable_macos-silicon.zip ./jabkit/build/packages/macos-15/jabkit.app && rm -R jabkit/build/packages/macos-15/jabkit.app",
"archivePortableJabLS": "7z a -r jabls-cli/build/packages/macos-15/jabls-portable_macos-silicon.zip ./jabls-cli/build/packages/macos-15/jabls.app && rm -R jabls-cli/build/packages/macos-15/jabls.app",
"suffix": "_silicon",
"archForDebianRepack": ""
}
]
}'
if [[ "$GITHUB_REF" != "refs/heads/main" && "$SHOULD_NOTARIZE" != "true" ]]; then
# drop macos-15-intel
MATRIX_JSON="$(jq -c ' .include |= map(select(.os != "macos-15-intel")) ' <<<"$MATRIX_JSON")"
else
# Format into one line for output, otherwise it cannot be used as matrix output
MATRIX_JSON="$(jq -c . <<<"$MATRIX_JSON")"
fi
echo "matrix=$MATRIX_JSON" >> "$GITHUB_OUTPUT"
build:
needs: [ compute-matrix, conditions, disk-space-check ]
if: ${{ needs.conditions.outputs.should-build == 'true' }}
strategy:
fail-fast: false
matrix:
${{ fromJSON(needs.compute-matrix.outputs.matrix) }}
runs-on: ${{ matrix.os }}
outputs:
major: ${{ steps.gitversion.outputs.Major }}
minor: ${{ steps.gitversion.outputs.Minor }}
branchname: ${{ steps.normalize.outputs.branch }}
url: ${{ steps.url.outputs.url }}
name: ${{ matrix.displayName }} installer and portable version
steps:
- name: Fetch all history for all tags and branches
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: 'true'
show-progress: 'false'
- name: Install GitVersion
id: pre-gitversion
# background: true
uses: gittools/actions/gitversion/setup@v3.2.1
with:
versionSpec: "5.x"
- name: Run GitVersion
# wait: pre-gitversion
# background: true
id: gitversion
uses: gittools/actions/gitversion/execute@v3.2.1
- name: Setup SSH key
if: ${{ needs.disk-space-check.outputs.available == 'true' }}
run: |
echo "${{ secrets.buildJabRefPrivateKey }}" > sshkey
chmod 600 sshkey
- name: Setup rsync (macOS)
if: ${{ (needs.disk-space-check.outputs.available == 'true') && (startsWith(matrix.os, 'macos')) }}
run: brew install rsync
- name: Setup rsync (Windows)
if: ${{ (needs.disk-space-check.outputs.available == 'true') && (matrix.os == 'windows-latest') }}
# We want to have rsync available at this place to avoid uploading and downloading from GitHub artifact store (taking > 5 minutes in total)
# We cannot use "action-rsyncer", because that requires Docker which is unavailable on Windows
# We cannot use "setup-rsync", because that does not work on Windows
# We do not use egor-tensin/setup-cygwin@v4, because it replaces the default shell
# We need to use v6.4.4 as v6.4.5 misses "lib\rsync\tools\bin\ssh.exe"
run: choco install rsync --version=6.4.4
- name: Patch used JDK
if: ${{ github.event_name == 'workflow_dispatch' && inputs.jvmVendor != 'AMAZON' }}
shell: bash
run: |
set -ex
PS4='+$LINENO: '
SED_I=(-i)
[[ '${{ startsWith(matrix.os, 'macos') }}' == 'true' ]] && SED_I=(-i '')
sed "${SED_I[@]}" "s/AMAZON/${{ inputs.jvmVendor }}/" build-logic/src/main/kotlin/org.jabref.gradle.feature.compile.gradle.kts
cat build-logic/src/main/kotlin/org.jabref.gradle.feature.compile.gradle.kts
# Setup JDK EA and JavaFX EA
- name: Set up latest JDK EA from jdk.java.net
if: ${{ needs.conditions.outputs.useEaJdk == 'true' }}
uses: oracle-actions/setup-java@v1
with:
website: jdk.java.net
release: EA
version: ${{ needs.conditions.outputs.jdkVersionFlavour }}
- name: Tell gradle to use JDK EA and JavaFX EA
if: ${{ needs.conditions.outputs.useEaJdk == 'true' }}
shell: bash
run: |
set -ex
PS4='+$LINENO: '
SED_I=(-i)
[[ '${{ startsWith(matrix.os, 'macos') }}' == 'true' ]] && SED_I=(-i '')
sed "${SED_I[@]}" "s/JavaLanguageVersion.of(25)/JavaLanguageVersion.of(${{ needs.conditions.outputs.jdkVersion }})/" build-logic/src/main/kotlin/org.jabref.gradle.feature.compile.gradle.kts
sed "${SED_I[@]}" "s/AMAZON/ORACLE/" build-logic/src/main/kotlin/org.jabref.gradle.feature.compile.gradle.kts
sed "${SED_I[@]}" "s|val javafx = .*|val javafx = \"${{ needs.conditions.outputs.javafxVersion }}\"|" versions/build.gradle.kts
- uses: ./.github/actions/setup-gradle
with:
distribution: ${{ needs.conditions.outputs.jvmDistribution }}
- name: Output current Java environment
shell: bash
run: |
set -x
echo $PATH
echo $JAVA_HOME
java -version
java -version >> $GITHUB_STEP_SUMMARY
javac -version
which jlink
jlink --version
- name: Normalize branch name
id: normalize
# wait: gitversion
shell: bash
run: |
branch="${{ steps.gitversion.outputs.EscapedBranchName }}"
branch="${branch%-merge}" # removes suffix only if present
if [[ "$branch" == tag* ]]; then
# tag builds go into a sub folder
branch="${{ steps.gitversion.outputs.BranchName }}"
fi
echo "branch=$branch" >> "$GITHUB_OUTPUT"
- name: Output URL
if: ${{ needs.disk-space-check.outputs.available == 'true' }}
shell: bash
id: url
run: |
echo "Link: https://builds.jabref.org/${{ steps.normalize.outputs.branch }}/"
echo "Link: <https://builds.jabref.org/${{ steps.normalize.outputs.branch }}/>" >> $GITHUB_STEP_SUMMARY
echo "url=https://builds.jabref.org/${{ steps.normalize.outputs.branch }}/" >> "$GITHUB_OUTPUT"
- name: Create backlink to PR at builds.jabref.org
# background: true
if: ${{ (github.event_name == 'pull_request') && (needs.disk-space-check.outputs.available == 'true') && (matrix.os == 'ubuntu-22.04') }}
run: |
echo "Link to PR: ${{ github.event.pull_request.html_url }}" >> _h5ai.header.md
rsync -rt --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r --itemize-changes --stats --rsync-path="mkdir -p /var/www/builds.jabref.org/www/${{ steps.normalize.outputs.branch }} && rsync" -e 'ssh -p 9922 -i sshkey -o StrictHostKeyChecking=no' _h5ai.header.md jrrsync@build-upload.jabref.org:/var/www/builds.jabref.org/www/${{ steps.normalize.outputs.branch }}/
# jablib is used by all components - thus, compile it first
- name: jablib jar
id: jablib-jar
# wait: gitversion
# background: true
run: ${{ matrix.gradleCommand }} :jablib:jar
env:
VERSION: ${{ steps.gitversion.outputs.AssemblySemVer }}
VERSION_INFO: ${{ steps.gitversion.outputs.InformationalVersion }}
# Save disk space
# Hint by https://dev.to/mathio/squeezing-disk-space-from-github-actions-runners-an-engineers-guide-3pjg
- run: sudo rm -rf /usr/local/lib/android/sdk
# background: true
if: startsWith(matrix.os, 'ubuntu')
- run: sudo rm -rf /usr/local/.ghcup
# background: true
if: startsWith(matrix.os, 'ubuntu')
- run: sudo rm -rf /usr/share/swift
# background: true
if: startsWith(matrix.os, 'ubuntu')
# Both JabRef Language Server and JabRef HTTP Server are required by the GUI
# They are independent from each other and could be build in parallel.
# - wait: jablib-jar # plus "normalize"
- name: jabls jar
# background: true
id: jabls-jar
run: ${{ matrix.gradleCommand }} :jabls:jar
env:
VERSION: ${{ steps.gitversion.outputs.AssemblySemVer }}
VERSION_INFO: ${{ steps.gitversion.outputs.InformationalVersion }}
- name: jabsrv jar
# background: true
id: jabsrv-jar
run: ${{ matrix.gradleCommand }} :jabsrv:jar
env:
VERSION: ${{ steps.gitversion.outputs.AssemblySemVer }}
VERSION_INFO: ${{ steps.gitversion.outputs.InformationalVersion }}
- name: Setup macOS key chain
if: (startsWith(matrix.os, 'macos')) && (needs.conditions.outputs.secretspresent == 'true')
uses: slidoapp/import-codesign-certs@1923310662e8682dd05b76b612b53301f431cd5d
with:
p12-file-base64: ${{ secrets.OSX_SIGNING_CERT }}
p12-password: ${{ secrets.OSX_CERT_PWD }}
keychain-password: tEmPoRaRY-PaeSWD
- name: Setup macOS key chain for app id cert
if: (startsWith(matrix.os, 'macos')) && (needs.conditions.outputs.secretspresent == 'true')
uses: slidoapp/import-codesign-certs@1923310662e8682dd05b76b612b53301f431cd5d
with:
p12-file-base64: ${{ secrets.OSX_SIGNING_CERT_APPLICATION }}
p12-password: ${{ secrets.OSX_CERT_PWD }}
create-keychain: false
keychain-password: tEmPoRaRY-PaeSWD
- name: Install jbundle
if: ${{ (matrix.os == 'ubuntu-22.04') && (needs.conditions.outputs.should-jbundle == 'true') }}
uses: baptiste0928/cargo-install@v3
with:
crate: jbundle
git: https://github.com/avelino/jbundle/
branch: main
- name: Install pigz and cache (Linux)
if: startsWith(matrix.os, 'ubuntu')
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: pigz
version: 1.0
- name: Workaround for jpackage issue
run: |
cd jabgui
cp buildres/linux/JabRef.png . # Linux
cp buildres/windows/JabRef.ico . # Windows
- name: Check WiX Version
run: candle -?
if: startsWith(matrix.os, 'windows')
# jars already exists - thus, these calls will build on the jar result (hopefully).
# - wait: [ jabls-jar, jabsrv-jar ]
- uses: ./.github/actions/package
name: Package JabRef Language Server
id: jabls-cli
# background: true
with:
gradleCommand: ${{ matrix.gradleCommand }}
component: jabls-cli
componentShort: jabls
branchName: ${{ steps.normalize.outputs.branch }}
AssemblySemVer: ${{ steps.gitversion.outputs.AssemblySemVer }}
Major: ${{ steps.gitversion.outputs.Major }}
Minor: ${{ steps.gitversion.outputs.Minor }}
InformationalVersion: ${{ steps.gitversion.outputs.InformationalVersion }}
diskSpaceAvailable: ${{ needs.disk-space-check.outputs.available }}
os: ${{ matrix.os }}
displayName: ${{ matrix.displayName }}
archivePortable: ${{ matrix.archivePortableJabLS }}
archForDebianRepack: ${{ matrix.archForDebianRepack }}
suffix: ${{ matrix.suffix }}
shouldJbundle: ${{ needs.conditions.outputs.should-jbundle }}
uploadAsArtifact: "${{ github.event.inputs.upload-as-artifact }}"
secretsPresent: "${{ needs.conditions.outputs.secretspresent }}"
astrophysicsDataSystemApiKey: ${{ secrets.AstrophysicsDataSystemAPIKey }}
biodiversityHeritageApiKey: ${{ secrets.BiodiversityHeritageApiKey }}
ieeeApiKey: ${{ secrets.IEEEAPIKey }}
springerNatureApiKey: ${{ secrets.SpringerNatureAPIKey }}
- uses: ./.github/actions/package
name: Package JabRef HTTP Server
# background: true
with:
gradleCommand: ${{ matrix.gradleCommand }}
component: jabsrv-cli
componentShort: jabsrv
branchName: ${{ steps.normalize.outputs.branch }}
AssemblySemVer: ${{ steps.gitversion.outputs.AssemblySemVer }}
Major: ${{ steps.gitversion.outputs.Major }}
Minor: ${{ steps.gitversion.outputs.Minor }}
InformationalVersion: ${{ steps.gitversion.outputs.InformationalVersion }}
diskSpaceAvailable: ${{ needs.disk-space-check.outputs.available }}
os: ${{ matrix.os }}
displayName: ${{ matrix.displayName }}
archivePortable: 'NONE'
archForDebianRepack: ${{ matrix.archForDebianRepack }}
suffix: ${{ matrix.suffix }}
shouldJbundle: ${{ needs.conditions.outputs.should-jbundle }}
uploadAsArtifact: "${{ github.event.inputs.upload-as-artifact }}"
secretsPresent: "${{ needs.conditions.outputs.secretspresent }}"
astrophysicsDataSystemApiKey: ${{ secrets.AstrophysicsDataSystemAPIKey }}
biodiversityHeritageApiKey: ${{ secrets.BiodiversityHeritageApiKey }}
ieeeApiKey: ${{ secrets.IEEEAPIKey }}
springerNatureApiKey: ${{ secrets.SpringerNatureAPIKey }}
- uses: ./.github/actions/package
name: Package JabGUI
id: jabgui
# background: true
with:
gradleCommand: ${{ matrix.gradleCommand }}
component: jabgui
componentShort: jabgui
branchName: ${{ steps.normalize.outputs.branch }}
AssemblySemVer: ${{ steps.gitversion.outputs.AssemblySemVer }}
Major: ${{ steps.gitversion.outputs.Major }}
Minor: ${{ steps.gitversion.outputs.Minor }}
InformationalVersion: ${{ steps.gitversion.outputs.InformationalVersion }}
diskSpaceAvailable: ${{ needs.disk-space-check.outputs.available }}
os: ${{ matrix.os }}
displayName: ${{ matrix.displayName }}
archivePortable: ${{ matrix.archivePortable }}
archForDebianRepack: ${{ matrix.archForDebianRepack }}
suffix: ${{ matrix.suffix }}
shouldJbundle: ${{ needs.conditions.outputs.should-jbundle }}
uploadAsArtifact: "${{ github.event.inputs.upload-as-artifact }}"
secretsPresent: "${{ needs.conditions.outputs.secretspresent }}"
astrophysicsDataSystemApiKey: ${{ secrets.AstrophysicsDataSystemAPIKey }}
biodiversityHeritageApiKey: ${{ secrets.BiodiversityHeritageApiKey }}
ieeeApiKey: ${{ secrets.IEEEAPIKey }}
springerNatureApiKey: ${{ secrets.SpringerNatureAPIKey }}
- uses: ./.github/actions/package
name: Package JabKit
# background: true
with:
gradleCommand: ${{ matrix.gradleCommand }}
component: jabkit
componentShort: jabkit
branchName: ${{ steps.normalize.outputs.branch }}
AssemblySemVer: ${{ steps.gitversion.outputs.AssemblySemVer }}
Major: ${{ steps.gitversion.outputs.Major }}
Minor: ${{ steps.gitversion.outputs.Minor }}
InformationalVersion: ${{ steps.gitversion.outputs.InformationalVersion }}
diskSpaceAvailable: ${{ needs.disk-space-check.outputs.available }}
os: ${{ matrix.os }}
displayName: ${{ matrix.displayName }}
archivePortable: ${{ matrix.archivePortableJabKit }}
archForDebianRepack: ${{ matrix.archForDebianRepack }}
suffix: ${{ matrix.suffix }}
shouldJbundle: ${{ needs.conditions.outputs.should-jbundle }}
uploadAsArtifact: "${{ github.event.inputs.upload-as-artifact }}"
secretsPresent: "${{ needs.conditions.outputs.secretspresent }}"
astrophysicsDataSystemApiKey: ${{ secrets.AstrophysicsDataSystemAPIKey }}
biodiversityHeritageApiKey: ${{ secrets.BiodiversityHeritageApiKey }}
ieeeApiKey: ${{ secrets.IEEEAPIKey }}
springerNatureApiKey: ${{ secrets.SpringerNatureAPIKey }}
- name: Upload jabgui and jabls-cli to GitHub workflow artifacts store for notarization (macOS)
if: ${{ (startsWith(matrix.os, 'macos')) && (needs.conditions.outputs.should-notarize == 'true') }}
# wait: [ jabgui, jabls-cli ]
uses: actions/upload-artifact@v7
with:
# tbn = to-be-notarized
name: JabRef-${{ matrix.os }}-tbn
path: |
jabgui/build/packages/${{ matrix.os }}
jabls-cli/build/packages/${{ matrix.os }}
compression-level: 0 # no compression
comment-on-issue-and-pr:
# separate job, because it should wait until all binaries are available
needs: [ conditions, disk-space-check, build ]
if: ${{ (github.event_name == 'pull_request') }}
permissions:
issues: write
pull-requests: write
runs-on: ubuntu-slim
steps:
- name: Comment PR
if: ${{ needs.disk-space-check.outputs.available == 'true' }}
uses: thollander/actions-comment-pull-request@v3
with:
message: |
The build of this PR is available at <${{ needs.build.outputs.url }}>.
comment-tag: download-link
mode: recreate
- name: Create GitHub Summary
if: ${{ needs.disk-space-check.outputs.available == 'true' }}
run: echo "The build of this PR is available at <${{ needs.build.outputs.url }}>." >> "$GITHUB_STEP_SUMMARY"
- name: echo PR data
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_URL: ${{ github.event.pull_request.html_url }}
PR_BODY: ${{ github.event.pull_request.body }}
run: |
echo "PR Number: $PR_NUMBER"
echo "PR URL: $PR_URL"
printf 'PR Body:\n%s\n' "$PR_BODY"
- name: Determine issue number
id: get_issue_number
uses: koppor/ticket-check-action@add-output
with:
token: ${{ secrets.GITHUB_TOKEN }}
ticketLink: 'https://github.com/JabRef/jabref/issues/%ticketNumber%'
ticketPrefix: '#'
titleRegex: '^#(?<ticketNumber>\d+)'
branchRegex: '^(?<ticketNumber>\d+)'
# Matches GitHub's closes/fixes/resolves #{number}, but does not match our example `Closes #13109` in PULL_REQUEST_TEMPLATE
bodyRegex: '(?<action>fixes|closes|resolves)\s+(?:https?:\/\/github\.com\/JabRef\/jabref\/issues\/)?#?(?<ticketNumber>(?!13109\b)\d+)'
bodyRegexFlags: 'i'
outputOnly: true
- name: Comment on issue (build available)
if: ${{ (steps.get_issue_number.outputs.ticketNumber != '-1') && (needs.disk-space-check.outputs.available == 'true') }}
uses: thollander/actions-comment-pull-request@v3
with:
pr-number: ${{ steps.get_issue_number.outputs.ticketNumber }}
message: >
A pull request addressing the issue has been created.
The build of this PR is available at <${{ needs.build.outputs.url }}>.
For any feedback, add a comment to the pull request at ${{ github.event.pull_request.html_url }}.
comment-tag: download-link
notarize:
# Outsourced in a separate job to be able to rerun if this fails for timeouts
name: macOS notarization - ${{ matrix.displayName }}
needs: [ conditions, build ]
if: ${{ needs.conditions.outputs.should-notarize == 'true' }}
strategy:
# Ensure that calls to Apple are sequentially made
max-parallel: 1
matrix:
include:
- os: macos-15
displayName: JabGui (macOS-silicon, notarized)
path: 'jabgui'
prefix: 'JabRef'
suffix: '_silicon'
- os: macos-15-intel
displayName: JabGui (macOS-intel, notarized)
path: 'jabgui'
prefix: 'JabRef'
suffix: '_intel'
# - os: macos-15
# displayName: jabls (macOS-silicon, notarized)
# path: 'jabls-cli'
# prefix: 'jabls'
# suffix: '_silicon'
# - os: macos-15-intel
# displayName: jabls (macOS-intel, notarized)
# path: 'jabls-cli'
# prefix: 'jabls'
# suffix: '_intel'
runs-on: ${{ matrix.os }}
steps:
- name: Download from GitHub workflow artifacts store (macOS)
uses: actions/download-artifact@v8
with:
name: JabRef-${{ matrix.os }}-tbn
- name: Notarize dmg
shell: bash
run: |
cd ${{ matrix.path }}
find . -type f
xcrun notarytool store-credentials "notarytool-profile" --apple-id "vorstand@jabref.org" --team-id "6792V39SK3" --password "${{ secrets.OSX_NOTARIZATION_APP_PWD }}"
xcrun notarytool submit build/packages/${{ matrix.os }}/${{ matrix.prefix }}-${{ needs.build.outputs.major }}.${{ needs.build.outputs.minor }}${{ matrix.suffix}}.dmg --keychain-profile "notarytool-profile" --wait
xcrun stapler staple build/packages/${{ matrix.os }}/${{ matrix.prefix }}-${{ needs.build.outputs.major }}.${{ needs.build.outputs.minor }}${{ matrix.suffix}}.dmg
- name: Notarize pkg
shell: bash
run: |
cd ${{ matrix.path }}
xcrun notarytool store-credentials "notarytool-profile" --apple-id "vorstand@jabref.org" --team-id "6792V39SK3" --password "${{ secrets.OSX_NOTARIZATION_APP_PWD }}"
xcrun notarytool submit build/packages/${{ matrix.os }}/${{ matrix.prefix }}-${{ needs.build.outputs.major }}.${{ needs.build.outputs.minor }}${{ matrix.suffix}}.pkg --keychain-profile "notarytool-profile" --wait
xcrun stapler staple build/packages/${{ matrix.os }}/${{ matrix.prefix }}-${{ needs.build.outputs.major }}.${{ needs.build.outputs.minor }}${{ matrix.suffix}}.pkg
- name: Upload to builds.jabref.org
if: needs.conditions.outputs.upload-to-builds-jabref-org == 'true'
shell: bash
run: |
echo "${{ secrets.buildJabRefPrivateKey }}" > sshkey
chmod 600 sshkey
rsync -rt --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r --itemize-changes --stats --rsync-path="mkdir -p /var/www/builds.jabref.org/www/${{ needs.build.outputs.branchname }} && rsync" -e 'ssh -p 9922 -i sshkey -o StrictHostKeyChecking=no' ${{ matrix.path }}/build/packages/${{ matrix.os }}/ jrrsync@build-upload.jabref.org:/var/www/builds.jabref.org/www/${{ needs.build.outputs.branchname }}/
- name: Upload artifacts
if: ${{ github.event.inputs.upload-as-artifact || 'false' == 'true' }}
uses: actions/upload-artifact@v7
with:
name: ${{ matrix.displayName }}
path: |
${{ matrix.path }}/build/packages/${{ matrix.os }}
upload-pr-nnumber:
runs-on: ubuntu-slim
permissions:
contents: read
actions: write
steps:
- name: Create pr_number.txt
run: echo "${{ github.event.pull_request.number }}" > pr_number.txt
- uses: actions/upload-artifact@v7
with:
name: pr_number
path: pr_number.txt