name: Build on: # Run on pushes to main and pushed tags, and on pull requests against main, but ignore the docs folder push: pull_request: concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} cancel-in-progress: true env: IMAGE_VERSION: v2026.0.6 jobs: validation: name: "Validation" runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: gradle/actions/wrapper-validation@v4 build-examples: strategy: fail-fast: false matrix: include: - os: windows-2022 architecture: x64 - os: macos-14 architecture: aarch64 - os: ubuntu-24.04 name: "Photonlib - Build Examples - ${{ matrix.os }}" runs-on: ${{ matrix.os }} needs: [validation] steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: git fetch --tags --force - name: Install Java 17 uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin - name: Install RoboRIO Toolchain run: ./gradlew installRoboRioToolchain - name: Delete duplicate toolchains run: | find ~/.gradle/cache/ -name *roborio-academic* -exec rm -rf {} + du -h . | sort -h if: matrix.os == 'ubuntu-24.04' # Need to publish to maven local first, so that C++ sim can pick it up - name: Publish photonlib to maven local run: ./gradlew photon-targeting:publishtomavenlocal photon-lib:publishtomavenlocal -x check - name: Build Java examples working-directory: photonlib-java-examples run: | ./gradlew build ./gradlew clean - name: Build C++ examples working-directory: photonlib-cpp-examples run: | ./gradlew build ./gradlew clean playwright-tests: name: "Playwright E2E tests" runs-on: ubuntu-24.04 needs: [validation] steps: # Checkout code. - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: git fetch --tags --force - name: Install Java 17 uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 10 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 22 - name: Setup tests working-directory: photon-client run: | pnpm install pnpm test-setup - name: Prebuild Gradle run: ./gradlew photon-targeting:build photon-core:build photon-server:build -x check - name: Run Playwright tests working-directory: photon-client run: pnpm test - uses: actions/upload-artifact@v4 if: ${{ !cancelled() }} with: name: playwright-report path: photon-client/playwright-report/ retention-days: 30 build-gradle: name: "Gradle Build" runs-on: ubuntu-24.04 needs: [validation] steps: # Checkout code. - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Fetch tags run: git fetch --tags --force - name: Install Java 17 uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 10 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 22 - name: Gradle Build run: ./gradlew photon-targeting:build photon-core:build photon-server:build -x check - name: Gradle Tests and Coverage run: ./gradlew test jacocoTestReport --stacktrace build-offline-docs: name: "Build Offline Docs" runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.12' - name: Install graphviz run: | sudo apt-get update sudo apt-get -y install graphviz - name: Install dependencies working-directory: docs run: | python -m pip install --upgrade pip pip install sphinx sphinx_rtd_theme sphinx-tabs sphinxext-opengraph doc8 pip install -r requirements.txt - name: Build the docs working-directory: docs run: | make html - uses: actions/upload-artifact@v4 with: name: built-docs path: docs/build/html build-photonlib-vendorjson: name: "Build Vendor JSON" runs-on: ubuntu-24.04 needs: [validation] steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install Java 17 uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin # grab all tags - run: git fetch --tags --force # Generate the JSON and give it the ""standard""" name maven gives it - run: | ./gradlew photon-lib:generateVendorJson export VERSION=$(git describe --tags --match=v*) mv photon-lib/build/generated/vendordeps/photonlib.json photon-lib/build/generated/vendordeps/photonlib-$(git describe --tags --match=v*).json # Upload it here so it shows up in releases - uses: actions/upload-artifact@v4 with: name: photonlib-vendor-json path: photon-lib/build/generated/vendordeps/photonlib-*.json build-photonlib-host: env: MACOSX_DEPLOYMENT_TARGET: 13 strategy: fail-fast: false matrix: include: - os: windows-2022 artifact-name: Win64 architecture: x64 - os: macos-14 artifact-name: macOS architecture: aarch64 - os: ubuntu-24.04 artifact-name: Linux name: "Photonlib - Build Host - ${{ matrix.artifact-name }}" runs-on: ${{ matrix.os }} needs: [validation] steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install Java 17 uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin architecture: ${{ matrix.architecture }} - run: git fetch --tags --force - run: ./gradlew photon-targeting:build photon-lib:build name: Build with Gradle - run: ./gradlew photon-lib:publish photon-targeting:publish name: Publish env: ARTIFACTORY_API_KEY: ${{ secrets.ARTIFACTORY_API_KEY }} if: github.event_name == 'push' && github.repository_owner == 'photonvision' # Copy artifacts to build/outputs/maven - run: ./gradlew photon-lib:publish photon-targeting:publish -PcopyOfflineArtifacts - uses: actions/upload-artifact@v4 with: name: maven-${{ matrix.artifact-name }} path: build/outputs build-photonlib-docker: strategy: fail-fast: false matrix: include: - container: wpilib/roborio-cross-ubuntu:2025-24.04 artifact-name: Athena build-options: "-Ponlylinuxathena" - container: wpilib/raspbian-cross-ubuntu:bullseye-22.04 artifact-name: Raspbian build-options: "-Ponlylinuxarm32" - container: wpilib/aarch64-cross-ubuntu:bullseye-22.04 artifact-name: Aarch64 build-options: "-Ponlylinuxarm64" runs-on: ubuntu-24.04 container: ${{ matrix.container }} name: "Photonlib - Build Docker - ${{ matrix.artifact-name }}" needs: [validation] steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Config Git run: | git config --global --add safe.directory /__w/photonvision/photonvision - name: Build PhotonLib # We don't need to run tests, since we specify only non-native platforms run: ./gradlew photon-targeting:build photon-lib:build ${{ matrix.build-options }} -x test - name: Publish run: ./gradlew photon-lib:publish photon-targeting:publish ${{ matrix.build-options }} env: ARTIFACTORY_API_KEY: ${{ secrets.ARTIFACTORY_API_KEY }} if: github.event_name == 'push' && github.repository_owner == 'photonvision' # Copy artifacts to build/outputs/maven - run: ./gradlew photon-lib:publish photon-targeting:publish -PcopyOfflineArtifacts ${{ matrix.build-options }} - uses: actions/upload-artifact@v4 with: name: maven-${{ matrix.artifact-name }} path: build/outputs combine: name: Combine needs: [build-photonlib-docker, build-photonlib-host] runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - run: git fetch --tags --force # download all maven-* artifacts to outputs/ - uses: actions/download-artifact@v7 with: merge-multiple: true path: output pattern: maven-* - run: find . - run: zip -r photonlib-$(git describe --tags --match=v*).zip . name: ZIP stuff up working-directory: output - run: ls output - uses: actions/upload-artifact@v4 with: name: photonlib-offline path: output/*.zip build-package: needs: [build-gradle, build-offline-docs] strategy: fail-fast: false matrix: include: - os: windows-latest artifact-name: Win64 architecture: x64 arch-override: winx64 - os: macos-latest artifact-name: macOS architecture: x64 arch-override: macx64 - os: macos-latest artifact-name: macOSArm architecture: x64 arch-override: macarm64 - os: ubuntu-24.04 artifact-name: Linux architecture: x64 arch-override: linuxx64 - os: ubuntu-24.04 artifact-name: LinuxArm64 architecture: x64 arch-override: linuxarm64 runs-on: ${{ matrix.os }} name: "Build fat JAR - ${{ matrix.artifact-name }}" steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install Java 17 uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin architecture: ${{ matrix.architecture }} - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 10 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 22 cache: pnpm cache-dependency-path: photon-client/pnpm-lock.yaml - name: Install Arm64 Toolchain run: ./gradlew installArm64Toolchain if: ${{ (matrix.artifact-name) == 'LinuxArm64' }} - uses: actions/download-artifact@v7 with: name: built-docs path: photon-server/src/main/resources/web/docs - run: ./gradlew photon-targeting:jar photon-server:shadowJar -PArchOverride=${{ matrix.arch-override }} if: ${{ (matrix.arch-override != 'none') }} - run: ./gradlew photon-server:shadowJar if: ${{ (matrix.arch-override == 'none') }} - uses: actions/upload-artifact@v4 with: name: jar-${{ matrix.artifact-name }} path: photon-server/build/libs - uses: actions/upload-artifact@v4 with: name: photon-targeting_jar-${{ matrix.artifact-name }} path: photon-targeting/build/libs run-smoketest-native: needs: [build-package] strategy: fail-fast: false matrix: include: - os: ubuntu-24.04 artifact-name: jar-Linux extraOpts: -Djdk.lang.Process.launchMechanism=vfork - os: windows-latest artifact-name: jar-Win64 - os: macos-latest artifact-name: jar-macOS architecture: x64 runs-on: ${{ matrix.os }} steps: - name: Install Java 17 uses: actions/setup-java@v4 with: java-version: 17 distribution: temurin - uses: actions/download-artifact@v7 with: name: ${{ matrix.artifact-name }} - run: java -jar ${{ matrix.extraOpts }} *.jar --smoketest if: ${{ (matrix.os) != 'windows-latest' }} - run: ls *.jar | %{ Write-Host "Running $($_.Name)"; Start-Process "java" -ArgumentList "-jar `"$($_.FullName)`" --smoketest" -NoNewWindow -Wait; break } if: ${{ (matrix.os) == 'windows-latest' }} build-image: needs: [build-package] strategy: fail-fast: false matrix: include: - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: RaspberryPi plat_override: LINUX_RASPBIAN64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_raspi.img.xz minimum_free_mb: 100 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: limelight2 plat_override: LINUX_RASPBIAN64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight.img.xz minimum_free_mb: 100 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: limelight3 plat_override: LINUX_RASPBIAN64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight3.img.xz minimum_free_mb: 100 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: limelight3G plat_override: LINUX_RASPBIAN64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight3g.img.xz minimum_free_mb: 100 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: limelight4 plat_override: LINUX_RASPBIAN64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_limelight4.img.xz minimum_free_mb: 100 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: luma_p1 plat_override: LINUX_RASPBIAN64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_luma_p1.img.xz minimum_free_mb: 100 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: orangepi5 plat_override: LINUX_RK3588_64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5.img.xz minimum_free_mb: 1024 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: orangepi5b plat_override: LINUX_RK3588_64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5b.img.xz minimum_free_mb: 1024 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: orangepi5plus plat_override: LINUX_RK3588_64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5plus.img.xz minimum_free_mb: 1024 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: orangepi5pro plat_override: LINUX_RK3588_64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5pro.img.xz minimum_free_mb: 1024 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: orangepi5max plat_override: LINUX_RK3588_64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_opi5max.img.xz minimum_free_mb: 1024 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: rock5c plat_override: LINUX_RK3588_64 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_rock5c.img.xz minimum_free_mb: 1024 - os: ubuntu-24.04-arm artifact-name: LinuxArm64 image_suffix: rubikpi3 plat_override: LINUX_QCS6490 image_url: https://github.com/PhotonVision/photon-image-modifier/releases/download/$IMAGE_VERSION/photonvision_rubikpi3.tar.xz minimum_free_mb: 1024 root_location: 'offset=569376768' shrink_image: 'no' runs-on: ${{ matrix.os }} name: "Build image - ${{ matrix.image_suffix }}" steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/download-artifact@v7 with: name: jar-${{ matrix.artifact-name }} - uses: photonvision/photon-image-runner@HEAD name: Generate image id: generate_image with: image_url: ${{ matrix.image_url }} minimum_free_mb: ${{ matrix.minimum_free_mb }} root_location: ${{ matrix.root_location || 'partition=2' }} shrink_image: ${{ matrix.shrink_image || 'yes' }} commands: | chmod +x scripts/armrunner.sh ./scripts/armrunner.sh java -jar *.jar --smoketest --platform=${{ matrix.plat_override }} - name: Compress image # Compress the standard images if: ${{ ! startsWith(matrix.image_suffix, 'rubik') }} run: | new_jar=$(realpath $(find . -name photonvision\*-linuxarm64.jar)) new_image_name=$(basename "${new_jar/.jar/_${{ matrix.image_suffix }}.img}") sudo mv ${{ steps.generate_image.outputs.image }} $new_image_name sudo xz -T 0 -v $new_image_name - name: Tar built image # Build the RubikPi3-specific tar file if: ${{ startsWith(matrix.image_suffix, 'rubik') }} run: | new_jar=$(realpath $(find . -name photonvision\*-linuxarm64.jar)) new_image_name=$(basename "${new_jar/.jar/_${{ matrix.image_suffix }}.img}") imagedir=$(dirname ${{ steps.generate_image.outputs.image }}) tardir=${new_image_name} sudo mkdir --parents ${tardir} sudo mv ${imagedir}/* ${tardir}/ sudo tar -I 'xz -T0' -cf ${new_image_name}.tar.xz ${tardir} --checkpoint=10000 --checkpoint-action=echo='%T' - uses: actions/upload-artifact@v4 name: Upload image with: name: image-${{ matrix.image_suffix }} path: photonvision*.xz matrix-checker: runs-on: ubuntu-latest needs: [build-image] if: always() steps: - run: ${{!contains(needs.*.result, 'failure')}} release: needs: [build-photonlib-vendorjson, build-package, build-image, combine] if: github.ref == ('refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) && github.repository == 'PhotonVision/photonvision' runs-on: ubuntu-24.04 steps: # Download all fat JARs - uses: actions/download-artifact@v7 with: merge-multiple: true pattern: jar-* # Download offline photonlib - uses: actions/download-artifact@v7 with: merge-multiple: true pattern: photonlib-offline # Download vendor json - uses: actions/download-artifact@v7 with: merge-multiple: true pattern: photonlib-vendor-json # Download all images - uses: actions/download-artifact@v7 with: merge-multiple: true pattern: image-* - run: find # Push to dev release - uses: pyTooling/Actions/releaser@r6 with: token: ${{ secrets.GITHUB_TOKEN }} tag: 'Dev' rm: true snapshots: false files: | **/*.xz **/*linux*.jar **/*win*.jar **/photonlib*.json **/photonlib*.zip if: github.event_name == 'push' - name: Create Vendor JSON Repo PR uses: wpilibsuite/vendor-json-repo/.github/actions/add_vendordep@main with: repo: PhotonVision/vendor-json-repo token: ${{ secrets.VENDOR_JSON_REPO_PUSH_TOKEN }} vendordep_file: ${{ github.workspace }}/photonlib-${{ github.ref_name }}.json pr_title: Update photonlib to ${{ github.ref_name }} pr_branch: photonlib-${{ github.ref_name }} if: github.repository == 'PhotonVision/photonvision' && startsWith(github.ref, 'refs/tags/v')