###################################################################################### # JME CI/CD ###################################################################################### # Quick overview of what is going on in this script: # - Build natives for android # - Merge the natives, build the engine, create the zip release, maven artifacts, javadoc and native snapshot # - (only when native code changes) Deploy the natives snapshot to the MinIO instance # - (only when building a release) Deploy everything else to github releases and Sonatype # - (only when building a release) Update javadoc.jmonkeyengine.org # Note: # All the actions/upload-artifact and actions/download-artifact steps are used to pass # stuff between jobs, github actions has some sort of storage that is local to the # running workflow, we use it to store the result of each job since the filesystem # is not maintained between jobs. ################# CONFIGURATIONS ##################################################### # >> Configure MINIO NATIVES SNAPSHOT # OBJECTS_KEY=XXXXXX # >> Configure SONATYPE RELEASE # CENTRAL_PASSWORD=XXXXXX # CENTRAL_USERNAME=XXXXXX # >> Configure SIGNING # SIGNING_KEY=XXXXXX # SIGNING_PASSWORD=XXXXXX # >> Configure PACKAGE REGISTRY RELEASE # Nothing to do here, everything is autoconfigured to work with the account/org that # is running the build. # >> Configure JAVADOC # JAVADOC_GHPAGES_REPO="riccardoblsandbox/javadoc.jmonkeyengine.org.git" # Generate a deploy key # ssh-keygen -t rsa -b 4096 -C "actions@users.noreply.github.com" -f javadoc_deploy # Set # JAVADOC_GHPAGES_DEPLOY_PRIVKEY="......." # In github repo -> Settings, use javadoc_deploy.pub as Deploy key with write access ###################################################################################### # Resources: # - Github actions docs: https://help.github.com/en/articles/about-github-actions # - Package registry docs: https://help.github.com/en/articles/about-github-package-registry # - Official actions: https://github.com/actions # - Community actions: https://github.com/sdras/awesome-actions ###################################################################################### # - Riccardo Balbo ###################################################################################### name: Build jMonkeyEngine on: push: branches: - master - v3.7 - v3.6 - v3.5 - v3.4 - v3.3 pull_request: release: types: [published] jobs: ScreenshotTests: name: Run Screenshot Tests runs-on: ubuntu-latest container: image: ghcr.io/onemillionworlds/opengl-docker-image:v1 permissions: contents: read steps: - uses: actions/checkout@v4 - name: Start xvfb run: | Xvfb :99 -ac -screen 0 1024x768x16 & export DISPLAY=:99 echo "DISPLAY=:99" >> $GITHUB_ENV - name: Report GL/Vulkan run: | set -x echo "DISPLAY=$DISPLAY" glxinfo | grep -E "OpenGL version|OpenGL renderer|OpenGL vendor" || true vulkaninfo --summary || true echo "VK_ICD_FILENAMES=$VK_ICD_FILENAMES" echo "MESA_LOADER_DRIVER_OVERRIDE=$MESA_LOADER_DRIVER_OVERRIDE" echo "GALLIUM_DRIVER=$GALLIUM_DRIVER" - name: Validate the Gradle wrapper uses: gradle/actions/wrapper-validation@v3 - name: Test with Gradle Wrapper run: | ./gradlew :jme3-screenshot-test:screenshotTest - name: Upload Test Reports uses: actions/upload-artifact@master if: always() with: name: screenshot-test-report retention-days: 30 path: | **/build/reports/** **/build/changed-images/** **/build/test-results/** # Build the natives on android BuildAndroidNatives: name: Build natives for android runs-on: ubuntu-latest container: image: ghcr.io/cirruslabs/android-sdk:35-ndk steps: - name: Clone the repo uses: actions/checkout@v4 with: fetch-depth: 1 - name: Setup Java 11 uses: actions/setup-java@v4 with: distribution: temurin java-version: '11' - name: Check java version run: java -version - name: Install CMake run: | apt-get update apt-get install -y cmake cmake --version - name: Validate the Gradle wrapper uses: gradle/actions/wrapper-validation@v3 - name: Build run: | export ANDROID_NDK="$ANDROID_SDK_ROOT/ndk/$ANDROID_NDK_VERSION" ./gradlew -PuseCommitHashAsVersionName=true --no-daemon -PbuildNativeProjects=true \ :jme3-android-native:assemble - name: Upload natives uses: actions/upload-artifact@master with: name: android-natives path: build/native # Build the engine, we only deploy from ubuntu-latest jdk21 BuildJMonkey: needs: [BuildAndroidNatives] name: Build on ${{ matrix.osName }} jdk${{ matrix.jdk }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest,windows-latest,macOS-latest] jdk: [11, 17, 21] include: - os: ubuntu-latest osName: linux deploy: true - os: windows-latest osName: windows deploy: false - os: macOS-latest osName: mac deploy: false - jdk: 11 deploy: false - jdk: 17 deploy: false steps: - name: Clone the repo uses: actions/checkout@v4 with: fetch-depth: 1 - name: Setup the java environment uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: ${{ matrix.jdk }} - name: Download natives for android uses: actions/download-artifact@master with: name: android-natives path: build/native - name: Validate the Gradle wrapper uses: gradle/actions/wrapper-validation@v3 - name: Build Engine shell: bash run: | # Normal build plus ZIP distribution and merged javadoc ./gradlew -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true \ build createZipDistribution mergedJavadoc if [ "${{ matrix.deploy }}" = "true" ]; then # We are going to need "zip" sudo apt-get update sudo apt-get install -y zip # We prepare the release for deploy mkdir -p ./dist/release/ mv build/distributions/*.zip dist/release/ # Install maven artifacts to ./dist/maven and sign them if possible if [ "${{ secrets.SIGNING_PASSWORD }}" = "" ]; then echo "Configure the following secrets to enable signing:" echo "SIGNING_KEY, SIGNING_PASSWORD" ./gradlew publishMavenPublicationToDistRepository \ -PskipPrebuildLibraries=true -PuseCommitHashAsVersionName=true \ --console=plain --stacktrace else ./gradlew publishMavenPublicationToDistRepository \ -PsigningKey='${{ secrets.SIGNING_KEY }}' \ -PsigningPassword='${{ secrets.SIGNING_PASSWORD }}' \ -PskipPrebuildLibraries=true -PuseCommitHashAsVersionName=true \ --console=plain --stacktrace fi # Zip the natives into a single archive (we are going to use this to deploy native snapshots) echo "Create native zip" cdir="$PWD" cd "build/native" zip -r "$cdir/dist/jme3-natives.zip" * cd "$cdir" echo "Done" fi # Used later by DeploySnapshot - name: Upload merged natives if: matrix.deploy==true uses: actions/upload-artifact@master with: name: natives path: dist/jme3-natives.zip # Upload maven artifacts to be used later by the deploy job - name: Upload maven artifacts if: matrix.deploy==true uses: actions/upload-artifact@master with: name: maven path: dist/maven - name: Upload javadoc if: matrix.deploy==true uses: actions/upload-artifact@master with: name: javadoc path: dist/javadoc # Upload release archive to be used later by the deploy job - name: Upload release if: github.event_name == 'release' && matrix.deploy==true uses: actions/upload-artifact@master with: name: release path: dist/release # This job deploys the native snapshot. # The snapshot is downloaded when people build the engine without setting buildNativeProject # this is useful for people that want to build only the java part and don't have # all the stuff needed to compile natives. DeployNativeSnapshot: needs: [BuildJMonkey] name: "Deploy native snapshot" runs-on: ubuntu-latest if: github.event_name == 'push' steps: # We clone the repo manually, since we are going to push back a reference to the snapshot - name: Clone the repo run: | branch="${GITHUB_REF//refs\/heads\//}" if [ "$branch" != "" ]; then git clone --single-branch --branch "$branch" https://github.com/${GITHUB_REPOSITORY}.git . fi - name: Download merged natives uses: actions/download-artifact@master with: name: natives path: dist/ - name: Deploy natives snapshot run: | source .github/actions/tools/minio.sh NATIVE_CHANGES="yes" branch="${GITHUB_REF//refs\/heads\//}" if [ "$branch" != "" ]; then if [ -f "natives-snapshot.properties" ]; then nativeSnapshot=`cat "natives-snapshot.properties"` nativeSnapshot="${nativeSnapshot#*=}" # We deploy ONLY if GITHUB_SHA (the current commit hash) is newer than $nativeSnapshot if [ "`git rev-list --count $nativeSnapshot..$GITHUB_SHA`" = "0" ]; then NATIVE_CHANGES="" else # We check if the native code changed. echo "Detect changes" NATIVE_CHANGES="$(git diff-tree --name-only "$GITHUB_SHA" "$nativeSnapshot" -- jme3-android-native/)" fi fi # We do nothing if there is no change if [ "$NATIVE_CHANGES" = "" ]; then echo "No changes, skip." else if [ "${{ secrets.OBJECTS_KEY }}" = "" ]; then echo "Configure the OBJECTS_KEY secret to enable natives snapshot deployment to MinIO" else # Deploy natives snapshot to a MinIO instance using function in minio.sh minio_uploadFile dist/jme3-natives.zip \ native-snapshots/$GITHUB_SHA/jme3-natives.zip \ https://objects.jmonkeyengine.org \ jmonkeyengine \ ${{ secrets.OBJECTS_KEY }} # We reference the snapshot by writing its commit hash in natives-snapshot.properties echo "natives.snapshot=$GITHUB_SHA" > natives-snapshot.properties # We commit the updated natives-snapshot.properties git config --global user.name "Github Actions" git config --global user.email "actions@users.noreply.github.com" git add natives-snapshot.properties git commit -m "[skip ci] update natives snapshot" # Pull rebase from the remote repo, just in case there was a push in the meantime git pull -q --rebase # We need to calculate the header for git authentication header=$(echo -n "ad-m:${{ secrets.GITHUB_TOKEN }}" | base64) # Push (git -c http.extraheader="AUTHORIZATION: basic $header" push origin "$branch" || true) fi fi fi # This job deploys snapshots on the master branch DeployJavaSnapshot: needs: [BuildJMonkey] name: Deploy Java Snapshot runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref_name == 'master' steps: # We need to clone everything again for uploadToMaven.sh ... - name: Clone the repo uses: actions/checkout@v4 with: fetch-depth: 1 # Setup jdk 21 used for building Maven-style artifacts - name: Setup the java environment uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '21' - name: Download natives for android uses: actions/download-artifact@master with: name: android-natives path: build/native - name: Rebuild the maven artifacts and upload them to Sonatype's maven-snapshots repo run: | if [ "${{ secrets.CENTRAL_PASSWORD }}" = "" ]; then echo "Configure the following secrets to enable uploading to Sonatype:" echo "CENTRAL_PASSWORD, CENTRAL_USERNAME, SIGNING_KEY, SIGNING_PASSWORD" else ./gradlew publishMavenPublicationToSNAPSHOTRepository \ -PcentralPassword=${{ secrets.CENTRAL_PASSWORD }} \ -PcentralUsername=${{ secrets.CENTRAL_USERNAME }} \ -PsigningKey='${{ secrets.SIGNING_KEY }}' \ -PsigningPassword='${{ secrets.SIGNING_PASSWORD }}' \ -PuseCommitHashAsVersionName=true \ --console=plain --stacktrace fi # This job deploys the release DeployRelease: needs: [BuildJMonkey] name: Deploy Release runs-on: ubuntu-latest if: github.event_name == 'release' steps: # We need to clone everything again for uploadToCentral.sh ... - name: Clone the repo uses: actions/checkout@v4 with: fetch-depth: 1 # Setup jdk 21 used for building Sonatype artifacts - name: Setup the java environment uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '21' # Download all the stuff... - name: Download maven artifacts uses: actions/download-artifact@master with: name: maven path: dist/maven - name: Download release uses: actions/download-artifact@master with: name: release path: dist/release - name: Download natives for android uses: actions/download-artifact@master with: name: android-natives path: build/native - name: Rebuild the maven artifacts and upload them to Sonatype's Central Publisher Portal run: | if [ "${{ secrets.CENTRAL_PASSWORD }}" = "" ]; then echo "Configure the following secrets to enable uploading to Sonatype:" echo "CENTRAL_PASSWORD, CENTRAL_USERNAME, SIGNING_KEY, SIGNING_PASSWORD" else ./gradlew publishMavenPublicationToCentralRepository \ -PcentralPassword=${{ secrets.CENTRAL_PASSWORD }} \ -PcentralUsername=${{ secrets.CENTRAL_USERNAME }} \ -PsigningKey='${{ secrets.SIGNING_KEY }}' \ -PsigningPassword='${{ secrets.SIGNING_PASSWORD }}' \ -PuseCommitHashAsVersionName=true \ --console=plain --stacktrace .github/actions/tools/uploadToCentral.sh \ -p '${{ secrets.CENTRAL_PASSWORD }}' \ -u '${{ secrets.CENTRAL_USERNAME }}' fi - name: Deploy to GitHub Releases run: | # We need to get the release id (yeah, it's not the same as the tag) echo "${GITHUB_EVENT_PATH}" cat ${GITHUB_EVENT_PATH} releaseId=$(jq --raw-output '.release.id' ${GITHUB_EVENT_PATH}) # Now that we have the id, we just upload the release zip from before echo "Upload to release $releaseId" filename="$(ls dist/release/*.zip)" url="https://uploads.github.com/repos/${GITHUB_REPOSITORY}/releases/$releaseId/assets?name=$(basename $filename)" echo "Upload to $url" curl -L \ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ -H "Content-Type: application/zip" \ --data-binary @"$filename" \ "$url" - name: Deploy to github package registry run: | source .github/actions/tools/uploadToMaven.sh registry="https://maven.pkg.github.com/$GITHUB_REPOSITORY" echo "Deploy to github package registry $registry" uploadAllToMaven dist/maven/ $registry "token" ${{ secrets.GITHUB_TOKEN }} # Deploy the javadoc DeployJavaDoc: needs: [BuildJMonkey] name: Deploy Javadoc runs-on: ubuntu-latest if: github.event_name == 'release' steps: # We are going to need a deploy key for this, since we need # to push to a different repo - name: Set ssh key run: | mkdir -p ~/.ssh/ echo "${{ secrets.JAVADOC_GHPAGES_DEPLOY_PRIVKEY }}" > $HOME/.ssh/deploy.key chmod 600 $HOME/.ssh/deploy.key # We clone the javadoc repo - name: Clone gh-pages run: | branch="gh-pages" export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i $HOME/.ssh/deploy.key" git clone --single-branch --branch "$branch" git@github.com:${{ secrets.JAVADOC_GHPAGES_REPO }} . # Download the javadoc in the new directory "newdoc" - name: Download javadoc uses: actions/download-artifact@master with: name: javadoc path: newdoc # The actual deploy - name: Deploy to github pages run: | set -f IFS=$'\n' # Get the tag for this release version="`if [[ $GITHUB_REF == refs\/tags* ]]; then echo ${GITHUB_REF//refs\/tags\//}; fi`" # If there is no tag, then we do nothing. if [ "$version" != "" ]; then echo "Deploy as $version" # Remove any older version of the javadoc for this tag if [ -d "$version" ];then rm -Rf "$version"; fi # Rename newdoc with the version name mv newdoc "$version" # if there isn't an index.txt we create one (we need this to list the versions) if [ ! -f "index.txt" ]; then echo "" > index.txt ; fi index="`cat index.txt`" # Check if this version is already in index.txt addNew=true for v in $index; do if [ "$v" = "$version" ]; then echo "$v" "$version" addNew=false break fi done # If not, we add it to the beginning if [ "$addNew" = "true" ]; then echo -e "$version\n$index" > index.txt index="`cat index.txt`" fi # Regenerate the pages chmod +x make.sh ./make.sh # Configure git to use the deploy key export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i $HOME/.ssh/deploy.key" # Commit the changes git config --global user.name "Github Actions" git config --global user.email "actions@users.noreply.github.com" git add . || true git commit -m "$version" || true branch="gh-pages" git push origin "$branch" --force || true fi