From 038e91c9b3dea8848c15b734f5ea681fb1d06dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Wed, 15 Apr 2026 16:38:34 -0400 Subject: [PATCH 01/20] build: add Conan package manager integration and fix Python build scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco Made-with: Cursor --- conan/profiles/x86_64_apple_debug | 2 +- conan/profiles/x86_64_apple_release | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conan/profiles/x86_64_apple_debug b/conan/profiles/x86_64_apple_debug index ce93271e6..ed2c6a09e 100644 --- a/conan/profiles/x86_64_apple_debug +++ b/conan/profiles/x86_64_apple_debug @@ -1,6 +1,6 @@ include(common) -# Host profile for Intel Mac (x86_64) or Rosetta 2 emulation on Apple Silicon (Debug). +# This a host profile for an x86_64 on Apple M1 (Debug). # Use that profile for -pr options. [settings] diff --git a/conan/profiles/x86_64_apple_release b/conan/profiles/x86_64_apple_release index 84b0f7add..ae095e6d5 100644 --- a/conan/profiles/x86_64_apple_release +++ b/conan/profiles/x86_64_apple_release @@ -1,6 +1,6 @@ include(common) -# Host profile for Intel Mac (x86_64) or Rosetta 2 emulation on Apple Silicon. +# This a host profile for an x86_64 on Apple M1. # Use that profile for -pr options. [settings] From 504e39a353cc9536e2cc19613b8a5c03dfdd61d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Wed, 15 Apr 2026 16:38:45 -0400 Subject: [PATCH 02/20] ci: add Conan CI workflow and update main CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9e9ad6bb..021d38bd0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ on: jobs: detect-changes: - if: github.repository_owner == 'AcademySoftwareFoundation' + #if: github.repository_owner == 'AcademySoftwareFoundation' runs-on: ubuntu-latest outputs: cmake_changed: ${{ steps.filter.outputs.cmake }} @@ -38,7 +38,7 @@ jobs: - '**/*.cmake' linux: - if: github.repository_owner == 'AcademySoftwareFoundation' + #if: github.repository_owner == 'AcademySoftwareFoundation' needs: detect-changes uses: ./.github/workflows/ci-linux.yml with: @@ -47,7 +47,7 @@ jobs: run_debug: ${{ github.event_name != 'pull_request' || needs.detect-changes.outputs.cmake_changed == 'true' }} macos: - if: github.repository_owner == 'AcademySoftwareFoundation' + #if: github.repository_owner == 'AcademySoftwareFoundation' needs: detect-changes uses: ./.github/workflows/ci-macos.yml with: @@ -56,7 +56,7 @@ jobs: run_debug: ${{ github.event_name != 'pull_request' || needs.detect-changes.outputs.cmake_changed == 'true' }} windows: - if: github.repository_owner == 'AcademySoftwareFoundation' + #if: github.repository_owner == 'AcademySoftwareFoundation' needs: detect-changes uses: ./.github/workflows/ci-windows.yml with: From 063e6ed3d06f761094fe3a38f7745213566d2b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Tue, 21 Apr 2026 12:13:35 -0400 Subject: [PATCH 03/20] Small tweaks and fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/ci.yml | 6 +++--- .github/workflows/conan.yml | 7 +++++++ cmake/macros/rv_create_std_deps_vars.cmake | 4 ++-- conan/profiles/x86_64_apple_debug | 2 +- conan/profiles/x86_64_apple_release | 2 +- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 021d38bd0..733dfb0a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: - '**/*.cmake' linux: - #if: github.repository_owner == 'AcademySoftwareFoundation' + if: github.repository_owner == 'AcademySoftwareFoundation' needs: detect-changes uses: ./.github/workflows/ci-linux.yml with: @@ -47,7 +47,7 @@ jobs: run_debug: ${{ github.event_name != 'pull_request' || needs.detect-changes.outputs.cmake_changed == 'true' }} macos: - #if: github.repository_owner == 'AcademySoftwareFoundation' + if: github.repository_owner == 'AcademySoftwareFoundation' needs: detect-changes uses: ./.github/workflows/ci-macos.yml with: @@ -56,7 +56,7 @@ jobs: run_debug: ${{ github.event_name != 'pull_request' || needs.detect-changes.outputs.cmake_changed == 'true' }} windows: - #if: github.repository_owner == 'AcademySoftwareFoundation' + if: github.repository_owner == 'AcademySoftwareFoundation' needs: detect-changes uses: ./.github/workflows/ci-windows.yml with: diff --git a/.github/workflows/conan.yml b/.github/workflows/conan.yml index 1263f611b..708c37ffc 100644 --- a/.github/workflows/conan.yml +++ b/.github/workflows/conan.yml @@ -12,6 +12,13 @@ on: env: SKIP_DEPS_CACHE: 'false' +<<<<<<< HEAD +======= + QT5_MODULES: 'debug_info qtcharts qtdatavis3d qtlottie qtnetworkauth qtquick3d qtquicktimeline qtscript qtwebengine qtwebglplugin' + ROCKY_QT5_ARCHIVES: 'icu qt3d qtbase qtconnectivity qtdeclarative qtgraphicaleffects qtimageformats qtlocation qtmultimedia qtquickcontrols qtquickcontrols2 qtremoteobjects qtscxml qtsensors qtsvg qttools qttranslations qtwayland qtwebchannel qtwebsockets qtwebview qtx11extras qtxmlpatterns' + MACOS_X86_64_QT5_ARCHIVES: 'd3dcompiler_47 opengl32sw qt3d qtactiveqt qtbase qtconnectivity qtdeclarative qtgraphicaleffects qtimageformats qtlocation qtmultimedia qtquickcontrols qtquickcontrols2 qtremoteobjects qtscxml qtsensors qtsvg qttools qttranslations qtwebchannel qtwebsockets qtwebview qtwinextras qtxmlpatterns' + WINDOWS_QT5_ARCHIVES: 'd3dcompiler_47 opengl32sw qt3d qtactiveqt qtbase qtconnectivity qtdeclarative qtgraphicaleffects qtimageformats qtlocation qtmultimedia qtquickcontrols qtquickcontrols2 qtremoteobjects qtscxml qtsensors qtsvg qttools qttranslations qtwebchannel qtwebsockets qtwebview qtwinextras qtxmlpatterns' +>>>>>>> 36705844 (Small tweaks and fixes) ROCKY_QT6_MODULES: 'debug_info qt3d qt5compat qtcharts qtconnectivity qtdatavis3d qtgrpc qthttpserver qtimageformats qtlanguageserver qtlocation qtlottie qtmultimedia qtnetworkauth qtpdf qtpositioning qtquick3d qtquick3dphysics qtquickeffectmaker qtquicktimeline qtremoteobjects qtscxml qtsensors qtserialbus qtserialport qtshadertools qtspeech qtvirtualkeyboard qtwaylandcompositor qtwebchannel qtwebengine qtwebsockets qtwebview' ROCKY_QT6_ARCHIVES: 'icu qtbase qtdeclarative qtsvg qttools qttranslations qtwayland' diff --git a/cmake/macros/rv_create_std_deps_vars.cmake b/cmake/macros/rv_create_std_deps_vars.cmake index 4e49f9540..1750869ed 100644 --- a/cmake/macros/rv_create_std_deps_vars.cmake +++ b/cmake/macros/rv_create_std_deps_vars.cmake @@ -894,7 +894,7 @@ FUNCTION(RV_BUILD_PKG_CONFIG_PATH _rbpcp_out_var) LIST(APPEND _rbpcp_dirs ${_RBPCP_EXTRA_DIRS}) ENDIF() - # 1. Dirs from found dependencies + # 2. Dirs from found dependencies GET_PROPERTY( _rbpcp_dep_dirs GLOBAL PROPERTY "RV_DEPS_PKG_CONFIG_PATH" @@ -903,7 +903,7 @@ FUNCTION(RV_BUILD_PKG_CONFIG_PATH _rbpcp_out_var) LIST(APPEND _rbpcp_dirs ${_rbpcp_dep_dirs}) ENDIF() - # 1. Environment PKG_CONFIG_PATH, filtered by CMAKE_IGNORE_PREFIX_PATH + # 3. Environment PKG_CONFIG_PATH, filtered by CMAKE_IGNORE_PREFIX_PATH SET(_rbpcp_env_path $ENV{PKG_CONFIG_PATH} ) diff --git a/conan/profiles/x86_64_apple_debug b/conan/profiles/x86_64_apple_debug index ed2c6a09e..ce93271e6 100644 --- a/conan/profiles/x86_64_apple_debug +++ b/conan/profiles/x86_64_apple_debug @@ -1,6 +1,6 @@ include(common) -# This a host profile for an x86_64 on Apple M1 (Debug). +# Host profile for Intel Mac (x86_64) or Rosetta 2 emulation on Apple Silicon (Debug). # Use that profile for -pr options. [settings] diff --git a/conan/profiles/x86_64_apple_release b/conan/profiles/x86_64_apple_release index ae095e6d5..84b0f7add 100644 --- a/conan/profiles/x86_64_apple_release +++ b/conan/profiles/x86_64_apple_release @@ -1,6 +1,6 @@ include(common) -# This a host profile for an x86_64 on Apple M1. +# Host profile for Intel Mac (x86_64) or Rosetta 2 emulation on Apple Silicon. # Use that profile for -pr options. [settings] From 9882e54de538ac04a16bc3e2507b1ab24c63c914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Wed, 22 Apr 2026 11:13:52 -0400 Subject: [PATCH 04/20] Set GCC 11 path in the profile for rocky 8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/conan.yml | 29 +++++++++++++++++++++++++++++ conan/profiles/x86_64_rocky8 | 5 +++++ conan/profiles/x86_64_rocky8_debug | 5 +++++ 3 files changed, 39 insertions(+) diff --git a/.github/workflows/conan.yml b/.github/workflows/conan.yml index 708c37ffc..c1ab6cdc5 100644 --- a/.github/workflows/conan.yml +++ b/.github/workflows/conan.yml @@ -153,9 +153,38 @@ jobs: echo "CC=/opt/rh/gcc-toolset-11/root/usr/bin/gcc" >> $GITHUB_ENV echo "CXX=/opt/rh/gcc-toolset-11/root/usr/bin/g++" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> $GITHUB_ENV + echo "LIBRARY_PATH=/opt/rh/gcc-toolset-11/root/usr/lib64:${LIBRARY_PATH:-}" >> $GITHUB_ENV gcc --version g++ --version + - name: Verify libstdc++ GLIBCXX versions for Rocky Linux 8 + if: ${{ matrix.rocky-version == '8' }} + run: | + echo "=== g++ -print-file-name=libstdc++.so ===" + GXX=/opt/rh/gcc-toolset-11/root/usr/bin/g++ + LIBSTDCXX_SO=$("$GXX" -print-file-name=libstdc++.so) + echo "libstdc++.so -> $LIBSTDCXX_SO" + ls -l "$LIBSTDCXX_SO" || true + file "$LIBSTDCXX_SO" || true + echo "--- contents (first 10 lines, in case it's a linker script) ---" + head -n 10 "$LIBSTDCXX_SO" || true + + echo "=== g++ -print-file-name=libstdc++.so.6 ===" + LIBSTDCXX_SO6=$("$GXX" -print-file-name=libstdc++.so.6) + echo "libstdc++.so.6 -> $LIBSTDCXX_SO6" + ls -l "$LIBSTDCXX_SO6" || true + + echo "=== System libstdc++.so.6 (/usr/lib64) ===" + ls -l /usr/lib64/libstdc++.so.6* || true + echo "GLIBCXX versions in /usr/lib64/libstdc++.so.6:" + strings /usr/lib64/libstdc++.so.6 | grep -E '^GLIBCXX_3\.4\.[0-9]+$' | sort -V | tail -n 10 || true + + echo "=== libstdc++_nonshared.a (gcc-toolset-11 nonshared symbols) ===" + find /opt/rh/gcc-toolset-11 -name 'libstdc++_nonshared.a' -print 2>/dev/null || true + + echo "=== Any newer libstdc++.so.6 under /opt/rh/gcc-toolset-11 ===" + find /opt/rh/gcc-toolset-11 -name 'libstdc++.so*' -print 2>/dev/null || true + - name: Check out repository code uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # 4.1.7 with: diff --git a/conan/profiles/x86_64_rocky8 b/conan/profiles/x86_64_rocky8 index 22c43ef20..89667259c 100644 --- a/conan/profiles/x86_64_rocky8 +++ b/conan/profiles/x86_64_rocky8 @@ -8,3 +8,8 @@ compiler.cppstd=17 compiler.libcxx=libstdc++11 compiler.version=11 os=Linux + +[buildenv] +# Use the default path for now +LD_LIBRARY_PATH=+(path)/opt/rh/gcc-toolset-11/root/usr/lib64 +LIBRARY_PATH=+(path)/opt/rh/gcc-toolset-11/root/usr/lib64 diff --git a/conan/profiles/x86_64_rocky8_debug b/conan/profiles/x86_64_rocky8_debug index fdfa66069..bda1174ca 100644 --- a/conan/profiles/x86_64_rocky8_debug +++ b/conan/profiles/x86_64_rocky8_debug @@ -8,3 +8,8 @@ compiler.cppstd=17 compiler.libcxx=libstdc++11 compiler.version=11 os=Linux + +[buildenv] +# Use the default path for now +LD_LIBRARY_PATH=+(path)/opt/rh/gcc-toolset-11/root/usr/lib64 +LIBRARY_PATH=+(path)/opt/rh/gcc-toolset-11/root/usr/lib64 From d789c530955e6b6b5d292d6b265ed57eb793293e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Wed, 22 Apr 2026 21:37:10 -0400 Subject: [PATCH 05/20] force openexr from source for conan with rocky 8 because of an issue with the openexr packages that has a different libstdc++ GLIBCXX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/conan.yml | 37 ------------------------------ conan/profiles/x86_64_rocky8 | 5 ---- conan/profiles/x86_64_rocky8_debug | 5 ---- 3 files changed, 47 deletions(-) diff --git a/.github/workflows/conan.yml b/.github/workflows/conan.yml index c1ab6cdc5..f40454e36 100644 --- a/.github/workflows/conan.yml +++ b/.github/workflows/conan.yml @@ -12,14 +12,6 @@ on: env: SKIP_DEPS_CACHE: 'false' -<<<<<<< HEAD -======= - QT5_MODULES: 'debug_info qtcharts qtdatavis3d qtlottie qtnetworkauth qtquick3d qtquicktimeline qtscript qtwebengine qtwebglplugin' - ROCKY_QT5_ARCHIVES: 'icu qt3d qtbase qtconnectivity qtdeclarative qtgraphicaleffects qtimageformats qtlocation qtmultimedia qtquickcontrols qtquickcontrols2 qtremoteobjects qtscxml qtsensors qtsvg qttools qttranslations qtwayland qtwebchannel qtwebsockets qtwebview qtx11extras qtxmlpatterns' - MACOS_X86_64_QT5_ARCHIVES: 'd3dcompiler_47 opengl32sw qt3d qtactiveqt qtbase qtconnectivity qtdeclarative qtgraphicaleffects qtimageformats qtlocation qtmultimedia qtquickcontrols qtquickcontrols2 qtremoteobjects qtscxml qtsensors qtsvg qttools qttranslations qtwebchannel qtwebsockets qtwebview qtwinextras qtxmlpatterns' - WINDOWS_QT5_ARCHIVES: 'd3dcompiler_47 opengl32sw qt3d qtactiveqt qtbase qtconnectivity qtdeclarative qtgraphicaleffects qtimageformats qtlocation qtmultimedia qtquickcontrols qtquickcontrols2 qtremoteobjects qtscxml qtsensors qtsvg qttools qttranslations qtwebchannel qtwebsockets qtwebview qtwinextras qtxmlpatterns' ->>>>>>> 36705844 (Small tweaks and fixes) - ROCKY_QT6_MODULES: 'debug_info qt3d qt5compat qtcharts qtconnectivity qtdatavis3d qtgrpc qthttpserver qtimageformats qtlanguageserver qtlocation qtlottie qtmultimedia qtnetworkauth qtpdf qtpositioning qtquick3d qtquick3dphysics qtquickeffectmaker qtquicktimeline qtremoteobjects qtscxml qtsensors qtserialbus qtserialport qtshadertools qtspeech qtvirtualkeyboard qtwaylandcompositor qtwebchannel qtwebengine qtwebsockets qtwebview' ROCKY_QT6_ARCHIVES: 'icu qtbase qtdeclarative qtsvg qttools qttranslations qtwayland' MACOX_X86_64_QT6_MODULES: 'debug_info qt3d qt5compat qtcharts qtconnectivity qtdatavis3d qtgrpc qthttpserver qtimageformats qtlanguageserver qtlocation qtlottie qtmultimedia qtnetworkauth qtpdf qtpositioning qtquick3d qtquick3dphysics qtquickeffectmaker qtquicktimeline qtremoteobjects qtscxml qtsensors qtserialbus qtserialport qtshadertools qtspeech qtvirtualkeyboard qtwebchannel qtwebengine qtwebsockets qtwebview' @@ -153,38 +145,9 @@ jobs: echo "CC=/opt/rh/gcc-toolset-11/root/usr/bin/gcc" >> $GITHUB_ENV echo "CXX=/opt/rh/gcc-toolset-11/root/usr/bin/g++" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> $GITHUB_ENV - echo "LIBRARY_PATH=/opt/rh/gcc-toolset-11/root/usr/lib64:${LIBRARY_PATH:-}" >> $GITHUB_ENV gcc --version g++ --version - - name: Verify libstdc++ GLIBCXX versions for Rocky Linux 8 - if: ${{ matrix.rocky-version == '8' }} - run: | - echo "=== g++ -print-file-name=libstdc++.so ===" - GXX=/opt/rh/gcc-toolset-11/root/usr/bin/g++ - LIBSTDCXX_SO=$("$GXX" -print-file-name=libstdc++.so) - echo "libstdc++.so -> $LIBSTDCXX_SO" - ls -l "$LIBSTDCXX_SO" || true - file "$LIBSTDCXX_SO" || true - echo "--- contents (first 10 lines, in case it's a linker script) ---" - head -n 10 "$LIBSTDCXX_SO" || true - - echo "=== g++ -print-file-name=libstdc++.so.6 ===" - LIBSTDCXX_SO6=$("$GXX" -print-file-name=libstdc++.so.6) - echo "libstdc++.so.6 -> $LIBSTDCXX_SO6" - ls -l "$LIBSTDCXX_SO6" || true - - echo "=== System libstdc++.so.6 (/usr/lib64) ===" - ls -l /usr/lib64/libstdc++.so.6* || true - echo "GLIBCXX versions in /usr/lib64/libstdc++.so.6:" - strings /usr/lib64/libstdc++.so.6 | grep -E '^GLIBCXX_3\.4\.[0-9]+$' | sort -V | tail -n 10 || true - - echo "=== libstdc++_nonshared.a (gcc-toolset-11 nonshared symbols) ===" - find /opt/rh/gcc-toolset-11 -name 'libstdc++_nonshared.a' -print 2>/dev/null || true - - echo "=== Any newer libstdc++.so.6 under /opt/rh/gcc-toolset-11 ===" - find /opt/rh/gcc-toolset-11 -name 'libstdc++.so*' -print 2>/dev/null || true - - name: Check out repository code uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # 4.1.7 with: diff --git a/conan/profiles/x86_64_rocky8 b/conan/profiles/x86_64_rocky8 index 89667259c..22c43ef20 100644 --- a/conan/profiles/x86_64_rocky8 +++ b/conan/profiles/x86_64_rocky8 @@ -8,8 +8,3 @@ compiler.cppstd=17 compiler.libcxx=libstdc++11 compiler.version=11 os=Linux - -[buildenv] -# Use the default path for now -LD_LIBRARY_PATH=+(path)/opt/rh/gcc-toolset-11/root/usr/lib64 -LIBRARY_PATH=+(path)/opt/rh/gcc-toolset-11/root/usr/lib64 diff --git a/conan/profiles/x86_64_rocky8_debug b/conan/profiles/x86_64_rocky8_debug index bda1174ca..fdfa66069 100644 --- a/conan/profiles/x86_64_rocky8_debug +++ b/conan/profiles/x86_64_rocky8_debug @@ -8,8 +8,3 @@ compiler.cppstd=17 compiler.libcxx=libstdc++11 compiler.version=11 os=Linux - -[buildenv] -# Use the default path for now -LD_LIBRARY_PATH=+(path)/opt/rh/gcc-toolset-11/root/usr/lib64 -LIBRARY_PATH=+(path)/opt/rh/gcc-toolset-11/root/usr/lib64 From 856b25aa369b3c0d212181eea26f939a045458cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Tue, 21 Apr 2026 12:13:35 -0400 Subject: [PATCH 06/20] Small tweaks and fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/conan.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/conan.yml b/.github/workflows/conan.yml index f40454e36..e7c7ffe8b 100644 --- a/.github/workflows/conan.yml +++ b/.github/workflows/conan.yml @@ -58,7 +58,8 @@ jobs: python-version: "3.11.8" vfx-platform: "CY2024" extra_repo: "powertools" - + conan-profile: "x86_64_rocky8" + - os: "ubuntu-latest" rocky-version: "9" image: "amd64/rockylinux:9" @@ -69,6 +70,7 @@ jobs: python-version: "3.11.8" vfx-platform: "CY2024" extra_repo: "crb" + conan-profile: "x86_64_rocky9" steps: - name: Display disk space @@ -337,7 +339,7 @@ jobs: - name: Build OpenRV main executable run: | - $CONAN_EXECUTABLE build conanfile.py --build=missing -pr:a ./conan/profiles/x86_64_rocky8 + $CONAN_EXECUTABLE build conanfile.py --build=missing -pr:a ./conan/profiles/${{ matrix.conan-profile }} - name: Tests run: | From 4c9742ee3c95be378e26176e6cf8851cf6a32a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Tue, 21 Apr 2026 13:26:33 -0400 Subject: [PATCH 07/20] Test openrv probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/ci.yml | 10 +- .github/workflows/conan-upload-test.yml | 289 ++++++++++++++++++++++++ conan/profiles/common | 5 +- 3 files changed, 298 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/conan-upload-test.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 733dfb0a3..8d7f18d4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,12 @@ name: OpenRV on: - push: - branches: - # This will run when PR is merged or direct pushes to main. - - main + # push: + # branches: + # # This will run when PR is merged or direct pushes to main. + # - main - pull_request: # This handles PR creation and subsequent commits. + # pull_request: # This handles PR creation and subsequent commits. schedule: # Midnight build every day diff --git a/.github/workflows/conan-upload-test.yml b/.github/workflows/conan-upload-test.yml new file mode 100644 index 000000000..0cfd65db2 --- /dev/null +++ b/.github/workflows/conan-upload-test.yml @@ -0,0 +1,289 @@ +name: Conan Upload Test (ASWF Artifactory) + +# Manual-only workflow for probing ASWF Artifactory write access and +# publishing prebuilt OpenRV packages under @openrv/vfxYYYY. +# +# Phases: +# probe = Phase A.5 only (upload a tiny dummy recipe to confirm +# the @openrv/* path is writable). ~2 min. +# openssl = Phase A.5 + B + C (probe, then build openssl/3.5.0 +# under @openrv/vfx2024 and upload). ~15 min. +# +# Target remote defaults to aswftesting (aswf-conan-dev) for safety. +# Switch to aswf (production) only after aswftesting succeeds and the +# namespace policy is confirmed + +on: + push: + branches: + # This will run when PR is merged or direct pushes to main. + - main + # Temporary: auto-run on the Conan-ASWF test branch while dispatch + # access is unavailable. Remove this line once testing is done. + - find-fork-test-aswf + + pull_request: # This handles PR creation and subsequent commits. + + workflow_dispatch: + inputs: + phase: + description: "Which phase to run" + required: true + default: "probe" + type: choice + options: + - probe + - openssl + remote: + description: "Target Conan remote" + required: true + default: "aswftesting" + type: choice + options: + - aswftesting + - aswf + +jobs: + upload: + name: "Conan ${{ inputs.phase || 'openssl' }} -> ${{ inputs.remote || 'aswftesting' }}" + runs-on: ubuntu-latest + container: + image: amd64/rockylinux:8 + + env: + CONAN_LOGIN_USERNAME: ${{ secrets.ARTIFACTORY_USER }} + CONAN_PASSWORD: ${{ secrets.ARTIFACTORY_TOKEN }} + # inputs.* is only populated for workflow_dispatch. For push / PR + # triggers these are empty, so fall back to safe defaults. + # TEMP: phase default is 'openssl' while we can't manually dispatch. + # Flip back to 'probe' once dispatch access is available again. + PHASE: ${{ inputs.phase || 'openssl' }} + REMOTE_NAME: ${{ inputs.remote || 'aswftesting' }} + REMOTE_URL: ${{ inputs.remote == 'aswf' && 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan' || 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan-dev' }} + CONAN_PROFILE: x86_64_rocky8 + # openssl 3.5.0 has been rotated out of CCI master. Use the latest + # 3.5.x patch available. Bump here when CCI drops 3.5.6 too. + OPENSSL_VERSION: "3.5.6" + # Match cmake-version from the rocky-linux matrix in conan.yml. + CMAKE_VERSION: "3.31.6" + + steps: + - name: Diagnose secret presence + # Prints lengths only (never values). If both are 0, the secrets + # aren't reaching this workflow. Likely causes: org-level secret + # with repo allow-list that excludes OpenRV, secrets placed under + # Environment / Dependabot / Codespaces tabs instead of Actions, + # or case/typo in the secret names. + env: + U: ${{ secrets.ARTIFACTORY_USER }} + T: ${{ secrets.ARTIFACTORY_TOKEN }} + run: | + echo "event: ${GITHUB_EVENT_NAME}" + echo "actor: ${GITHUB_ACTOR}" + echo "repo: ${GITHUB_REPOSITORY}" + echo "ref: ${GITHUB_REF}" + echo "ARTIFACTORY_USER length: ${#U}" + echo "ARTIFACTORY_TOKEN length: ${#T}" + echo "CONAN_LOGIN_USERNAME (env) length: ${#CONAN_LOGIN_USERNAME}" + echo "CONAN_PASSWORD (env) length: ${#CONAN_PASSWORD}" + + - name: Verify secrets are set + run: | + if [ -z "$CONAN_LOGIN_USERNAME" ] || [ -z "$CONAN_PASSWORD" ]; then + echo "::error::ARTIFACTORY_USER or ARTIFACTORY_TOKEN secret is not set on this repo." + exit 1 + fi + + - name: Install base system packages + run: | + dnf install -y epel-release + dnf config-manager --set-enabled powertools devel + dnf groupinstall "Development Tools" -y + dnf install -y which findutils git python3 python3-pip perl perl-IPC-Cmd perl-Digest-SHA nasm make + dnf clean all + + - name: Install gcc-toolset-11 + run: | + for i in 1 2 3 4 5; do + dnf install -y gcc-toolset-11-toolchain && break + echo "attempt $i failed, retrying in 5s"; sleep 5 + done + + - name: Enable gcc-toolset-11 + run: | + source /opt/rh/gcc-toolset-11/enable + echo "/opt/rh/gcc-toolset-11/root/usr/bin" >> $GITHUB_PATH + echo "CC=/opt/rh/gcc-toolset-11/root/usr/bin/gcc" >> $GITHUB_ENV + echo "CXX=/opt/rh/gcc-toolset-11/root/usr/bin/g++" >> $GITHUB_ENV + gcc --version + + - name: Install CMake + # Same pattern as .github/actions/build-linux/action.yml: download + # the Kitware binary tarball instead of relying on dnf. + run: | + curl -SL -o cmake.tar.gz "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz" + tar -xzf cmake.tar.gz + mv "cmake-${CMAKE_VERSION}-linux-x86_64" "./cmake-${CMAKE_VERSION}" + echo "$(pwd)/cmake-${CMAKE_VERSION}/bin" >> $GITHUB_PATH + "$(pwd)/cmake-${CMAKE_VERSION}/bin/cmake" --version + + - name: Install Conan 2.x + run: | + python3 -m pip install --upgrade pip + python3 -m pip install "conan>=2.0,<3.0" + conan --version + + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + submodules: false + + - name: Mark repo as safe git directory + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + + - name: Configure Conan remote and authenticate + run: | + # Replace any existing entry so the URL is always the one we expect. + conan remote remove "$REMOTE_NAME" 2>/dev/null || true + conan remote add "$REMOTE_NAME" "$REMOTE_URL" --index 0 + conan remote list + conan remote login "$REMOTE_NAME" "$CONAN_LOGIN_USERNAME" -p "$CONAN_PASSWORD" + + - name: Detect default Conan profile + # The x86_64_rocky8 profile inherits no fallback, so a baseline + # "default" profile must exist for conan create to resolve. + run: conan profile detect --force + + - name: Phase A.5 - Create probe recipe + run: | + mkdir -p /tmp/openrv-probe + cat > /tmp/openrv-probe/conanfile.py <<'PY' + from conan import ConanFile + + class Probe(ConanFile): + name = "openrv-probe" + version = "0.0.1" + package_type = "application" + settings = "os", "arch" + + def package(self): + pass + PY + conan create /tmp/openrv-probe --user openrv --channel test + + - name: Phase A.5 - Upload probe to ${{ inputs.remote || 'aswftesting' }} + id: probe_upload + run: | + set +e + out=$(conan upload "openrv-probe/0.0.1@openrv/test" --remote "$REMOTE_NAME" --confirm 2>&1) + status=$? + echo "$out" + echo "----" + if [ $status -eq 0 ]; then + echo "::notice::Probe upload succeeded. @openrv/* writes are permitted on $REMOTE_NAME." + else + if echo "$out" | grep -qiE "403|forbidden|unauthorized"; then + echo "::error::Probe upload rejected. Check LF Artifactory permission target for aswf-conan*/openrv/**." + fi + exit $status + fi + + - name: Phase A.5 - Clean up probe from remote + if: always() && steps.probe_upload.outcome == 'success' + continue-on-error: true + run: | + conan remove "openrv-probe/*" -r "$REMOTE_NAME" -c || true + conan remove "openrv-probe/*" -c || true + + - name: Phase B - Clone conan-center-index and verify openssl version + if: ${{ env.PHASE == 'openssl' }} + run: | + git clone --depth 1 --branch master https://github.com/conan-io/conan-center-index.git /tmp/cci + echo "::group::CCI openssl config.yml" + cat /tmp/cci/recipes/openssl/config.yml + echo "::endgroup::" + # Fail early if the pinned OPENSSL_VERSION isn't listed in CCI. + if ! grep -q "\"${OPENSSL_VERSION}\"" /tmp/cci/recipes/openssl/config.yml; then + echo "::error::openssl ${OPENSSL_VERSION} not found in CCI config.yml. Update OPENSSL_VERSION env." + exit 1 + fi + + - name: Phase B - Build openssl/${{ env.OPENSSL_VERSION }}@openrv/vfx2024 + if: ${{ env.PHASE == 'openssl' }} + run: | + # -tf="" skips the CCI test_package step; we only care about + # producing and uploading the binary, not revalidating the recipe. + conan create /tmp/cci/recipes/openssl/3.x.x/ \ + --version "${OPENSSL_VERSION}" \ + --user openrv \ + --channel vfx2024 \ + --build=missing \ + -tf="" \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" \ + -o 'openssl/*:shared=True' \ + -o 'openssl/*:no_zlib=True' + conan list "openssl/${OPENSSL_VERSION}@openrv/vfx2024:*" + + - name: Phase C - Upload openssl/${{ env.OPENSSL_VERSION }}@openrv/vfx2024 + if: ${{ env.PHASE == 'openssl' }} + run: | + conan upload "openssl/${OPENSSL_VERSION}@openrv/vfx2024" --remote "$REMOTE_NAME" --confirm + + - name: Verify server-side listing + if: ${{ env.PHASE == 'openssl' }} + run: conan search "openssl/${OPENSSL_VERSION}@openrv/vfx2024" -r "$REMOTE_NAME" + + - name: Phase D - Wipe local cache for openssl + if: ${{ env.PHASE == 'openssl' }} + run: | + # Remove the just-built package so the install in the next step + # has to pull from the remote. Otherwise conan would use the + # local cache and we would not be exercising the remote. + conan remove "openssl/${OPENSSL_VERSION}@openrv/vfx2024" -c + + - name: Phase D - Round-trip install from ${{ inputs.remote || 'aswftesting' }} + if: ${{ env.PHASE == 'openssl' }} + run: | + # --build=never makes this step assert "prebuilt binary must + # exist on the remote with the same package_id as the profile + # and options below produce". If Conan would need to build, it + # fails here and we know the upload was incomplete or the + # options do not match what was uploaded. + set -o pipefail + conan install \ + --requires="openssl/${OPENSSL_VERSION}@openrv/vfx2024" \ + -r "$REMOTE_NAME" \ + --build=never \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" \ + -o 'openssl/*:shared=True' \ + -o 'openssl/*:no_zlib=True' 2>&1 | tee /tmp/phase_d.log + + if grep -qiE "Building from sources|building package" /tmp/phase_d.log; then + echo "::error::Phase D regressed - Conan is building instead of downloading." + exit 1 + fi + if ! grep -qiE "downloaded|Already installed" /tmp/phase_d.log; then + echo "::error::Phase D log does not show a download or cache hit from $REMOTE_NAME." + exit 1 + fi + echo "::notice::Phase D success - openssl/${OPENSSL_VERSION}@openrv/vfx2024 is consumable from $REMOTE_NAME without a rebuild." + + - name: Phase E - Verify profile rewrites openssl to @openrv/vfx2024 + if: ${{ env.PHASE == 'openssl' }} + run: | + # conan/profiles/common has [replace_requires] that rewrites + # openssl/* to openssl/${OPENSSL_VERSION}@openrv/vfx2024. Asking + # for plain openssl/3.5.0 should still resolve to the ASWF ref. + set -o pipefail + conan graph info \ + --requires="openssl/3.5.0" \ + -r "$REMOTE_NAME" \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" \ + -o 'openssl/*:shared=True' \ + -o 'openssl/*:no_zlib=True' 2>&1 | tee /tmp/phase_e.log + + expected_ref="openssl/${OPENSSL_VERSION}@openrv/vfx2024" + if ! grep -qF "$expected_ref" /tmp/phase_e.log; then + echo "::error::Phase E failed - graph does not contain $expected_ref. The profile replace_requires rewrite is not taking effect." + exit 1 + fi + echo "::notice::Phase E success - profile rewrites openssl/* to $expected_ref." diff --git a/conan/profiles/common b/conan/profiles/common index 320bde179..2188b06eb 100644 --- a/conan/profiles/common +++ b/conan/profiles/common @@ -1,5 +1,8 @@ # Common settings shared across all OpenRV profiles [replace_requires] -openssl/*: openssl/3.5.0 +# openssl resolves to the prebuilt binary hosted under @openrv/vfx2024 +# on the ASWF Conan remote (aswf-conan-dev / aswf-conan). Consumers must +# have one of those remotes configured to resolve this reference. +openssl/*: openssl/3.5.6@openrv/vfx2024 libjpeg/*: libjpeg-turbo/2.1.4 From cc5f3039839906b88a0d14a984b95b33a60aa8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Wed, 22 Apr 2026 10:21:07 -0400 Subject: [PATCH 08/20] test openssl from aswftesting for rocky 8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/conan.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/conan.yml b/.github/workflows/conan.yml index e7c7ffe8b..72750cf20 100644 --- a/.github/workflows/conan.yml +++ b/.github/workflows/conan.yml @@ -311,6 +311,18 @@ jobs: echo "Conan home path: $CONAN_HOME_OUTPUT" echo "CONAN_HOME=$CONAN_HOME_OUTPUT" >> $GITHUB_ENV + - name: Add ASWF Conan remote + # Required so conan/profiles/common [replace_requires] can resolve + # openssl/*@openrv/vfx2024 from the ASWF JFrog Artifactory. + # Anonymous read; no credentials needed for install. Uses aswftesting + # (aswf-conan-dev) for now; swap to the 'aswf' production remote + # once binaries are promoted there. + # Rocky 8 currently has a prebuilt binary; other profiles will + # build from source via the CCI recipe exported under this user/channel. + run: | + $CONAN_EXECUTABLE remote remove aswftesting 2>/dev/null || true + $CONAN_EXECUTABLE remote add aswftesting https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan-dev --index 0 + - name: Export OpenRVCore recipe to Conan's cache if: ${{ matrix.vfx-platform == 'CY2024' }} run: | @@ -492,6 +504,12 @@ jobs: - name: Set Conan Home Path run: echo "CONAN_HOME=$(/Users/runner/Library/Python/3.11/bin/conan config home)" >> $GITHUB_ENV + - name: Add ASWF Conan remote + # See conan.yml Rocky step of the same name for rationale. + run: | + /Users/runner/Library/Python/3.11/bin/conan remote remove aswftesting 2>/dev/null || true + /Users/runner/Library/Python/3.11/bin/conan remote add aswftesting https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan-dev --index 0 + - name: Export OpenRVCore recipe if: ${{ matrix.vfx-platform == 'CY2024' }} run: | @@ -737,6 +755,14 @@ jobs: cat ~/.bash_profile | tail -5 shell: msys2 {0} + - name: Add ASWF Conan remote + # See conan.yml Rocky step of the same name for rationale. + run: | + source ~/.bash_profile + conan remote remove aswftesting 2>/dev/null || true + conan remote add aswftesting https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan-dev --index 0 + shell: msys2 {0} + - name: Export OpenRVCore recipe if: ${{ matrix.vfx-platform == 'CY2024' }} run: | From ff2d14e3833734dab3033693882218fdb2dcd064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Thu, 23 Apr 2026 10:21:41 -0400 Subject: [PATCH 09/20] Probe test all platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/conan-upload-test.yml | 493 +++++++++++++++++++++--- 1 file changed, 437 insertions(+), 56 deletions(-) diff --git a/.github/workflows/conan-upload-test.yml b/.github/workflows/conan-upload-test.yml index 0cfd65db2..64f6df0eb 100644 --- a/.github/workflows/conan-upload-test.yml +++ b/.github/workflows/conan-upload-test.yml @@ -5,21 +5,22 @@ name: Conan Upload Test (ASWF Artifactory) # # Phases: # probe = Phase A.5 only (upload a tiny dummy recipe to confirm -# the @openrv/* path is writable). ~2 min. -# openssl = Phase A.5 + B + C (probe, then build openssl/3.5.0 -# under @openrv/vfx2024 and upload). ~15 min. +# the @openrv/* path is writable). ~2 min per platform. +# openssl = Phase A.5 + B + C + D + E (probe, then build openssl +# under @openrv/vfx2024, upload, round-trip install, +# profile graph verify). 10-20 min per platform. # # Target remote defaults to aswftesting (aswf-conan-dev) for safety. # Switch to aswf (production) only after aswftesting succeeds and the -# namespace policy is confirmed +# namespace policy is confirmed. on: push: branches: # This will run when PR is merged or direct pushes to main. - main - # Temporary: auto-run on the Conan-ASWF test branch while dispatch - # access is unavailable. Remove this line once testing is done. + # Temporary: auto-run on the Conan-ASWF test branch while manual + # workflow dispatch is not available. Remove once testing is done. - find-fork-test-aswf pull_request: # This handles PR creation and subsequent commits. @@ -42,38 +43,57 @@ on: options: - aswftesting - aswf + platforms: + description: "Comma-separated subset of rocky8,rocky9,macos,windows (empty = all)" + required: false + default: "rocky8,rocky9,macos,windows" + +env: + # Shared across all jobs. Not platform-dependent. + OPENSSL_VERSION: "3.5.6" + CMAKE_VERSION: "3.31.6" + # inputs.* is only populated for workflow_dispatch. For push / PR + # triggers these are empty; each job applies its own fallback. + PHASE: ${{ inputs.phase || 'probe' }} + REMOTE_NAME: ${{ inputs.remote || 'aswftesting' }} + REMOTE_URL: ${{ inputs.remote == 'aswf' && 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan' || 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan-dev' }} + PLATFORMS: ${{ inputs.platforms || 'rocky8,rocky9,macos,windows' }} jobs: - upload: - name: "Conan ${{ inputs.phase || 'openssl' }} -> ${{ inputs.remote || 'aswftesting' }}" + # --------------------------------------------------------------------------- + # Rocky Linux (8 + 9). Matrix over rocky-version; job runs per row. + # --------------------------------------------------------------------------- + rocky-linux: + name: "Conan ${{ inputs.phase || 'probe' }} -> rocky${{ matrix.rocky-version }} -> ${{ inputs.remote || 'aswftesting' }}" + # GitHub Actions does not expose matrix.* in job-level if: expressions, + # so we cannot filter rocky8 vs rocky9 independently here. If either + # token appears in platforms, both matrix rows run; if neither does, + # neither runs. Selecting "rocky8 only" requires editing the matrix. + if: contains(format(',{0},', inputs.platforms || 'rocky8,rocky9,macos,windows'), ',rocky8,') || contains(format(',{0},', inputs.platforms || 'rocky8,rocky9,macos,windows'), ',rocky9,') runs-on: ubuntu-latest container: - image: amd64/rockylinux:8 + image: ${{ matrix.image }} + + strategy: + fail-fast: false + matrix: + include: + - rocky-version: "8" + image: "amd64/rockylinux:8" + extra_repo: "powertools" + conan-profile: "x86_64_rocky8" + - rocky-version: "9" + image: "amd64/rockylinux:9" + extra_repo: "crb" + conan-profile: "x86_64_rocky9" env: CONAN_LOGIN_USERNAME: ${{ secrets.ARTIFACTORY_USER }} CONAN_PASSWORD: ${{ secrets.ARTIFACTORY_TOKEN }} - # inputs.* is only populated for workflow_dispatch. For push / PR - # triggers these are empty, so fall back to safe defaults. - # TEMP: phase default is 'openssl' while we can't manually dispatch. - # Flip back to 'probe' once dispatch access is available again. - PHASE: ${{ inputs.phase || 'openssl' }} - REMOTE_NAME: ${{ inputs.remote || 'aswftesting' }} - REMOTE_URL: ${{ inputs.remote == 'aswf' && 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan' || 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan-dev' }} - CONAN_PROFILE: x86_64_rocky8 - # openssl 3.5.0 has been rotated out of CCI master. Use the latest - # 3.5.x patch available. Bump here when CCI drops 3.5.6 too. - OPENSSL_VERSION: "3.5.6" - # Match cmake-version from the rocky-linux matrix in conan.yml. - CMAKE_VERSION: "3.31.6" + CONAN_PROFILE: ${{ matrix.conan-profile }} steps: - name: Diagnose secret presence - # Prints lengths only (never values). If both are 0, the secrets - # aren't reaching this workflow. Likely causes: org-level secret - # with repo allow-list that excludes OpenRV, secrets placed under - # Environment / Dependabot / Codespaces tabs instead of Actions, - # or case/typo in the secret names. env: U: ${{ secrets.ARTIFACTORY_USER }} T: ${{ secrets.ARTIFACTORY_TOKEN }} @@ -82,6 +102,7 @@ jobs: echo "actor: ${GITHUB_ACTOR}" echo "repo: ${GITHUB_REPOSITORY}" echo "ref: ${GITHUB_REF}" + echo "platform: rocky${{ matrix.rocky-version }} (${{ matrix.conan-profile }})" echo "ARTIFACTORY_USER length: ${#U}" echo "ARTIFACTORY_TOKEN length: ${#T}" echo "CONAN_LOGIN_USERNAME (env) length: ${#CONAN_LOGIN_USERNAME}" @@ -97,19 +118,21 @@ jobs: - name: Install base system packages run: | dnf install -y epel-release - dnf config-manager --set-enabled powertools devel + dnf config-manager --set-enabled ${{ matrix.extra_repo }} devel dnf groupinstall "Development Tools" -y dnf install -y which findutils git python3 python3-pip perl perl-IPC-Cmd perl-Digest-SHA nasm make dnf clean all - - name: Install gcc-toolset-11 + - name: Install gcc-toolset-11 (rocky8 only) + if: matrix.rocky-version == '8' run: | for i in 1 2 3 4 5; do dnf install -y gcc-toolset-11-toolchain && break echo "attempt $i failed, retrying in 5s"; sleep 5 done - - name: Enable gcc-toolset-11 + - name: Enable gcc-toolset-11 (rocky8 only) + if: matrix.rocky-version == '8' run: | source /opt/rh/gcc-toolset-11/enable echo "/opt/rh/gcc-toolset-11/root/usr/bin" >> $GITHUB_PATH @@ -117,9 +140,13 @@ jobs: echo "CXX=/opt/rh/gcc-toolset-11/root/usr/bin/g++" >> $GITHUB_ENV gcc --version + - name: Install Rocky 9 perl CPAN (rocky9 only) + if: matrix.rocky-version == '9' + run: | + dnf install -y perl-CPAN + cpan FindBin || true + - name: Install CMake - # Same pattern as .github/actions/build-linux/action.yml: download - # the Kitware binary tarball instead of relying on dnf. run: | curl -SL -o cmake.tar.gz "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz" tar -xzf cmake.tar.gz @@ -142,15 +169,12 @@ jobs: - name: Configure Conan remote and authenticate run: | - # Replace any existing entry so the URL is always the one we expect. conan remote remove "$REMOTE_NAME" 2>/dev/null || true conan remote add "$REMOTE_NAME" "$REMOTE_URL" --index 0 conan remote list conan remote login "$REMOTE_NAME" "$CONAN_LOGIN_USERNAME" -p "$CONAN_PASSWORD" - name: Detect default Conan profile - # The x86_64_rocky8 profile inherits no fallback, so a baseline - # "default" profile must exist for conan create to resolve. run: conan profile detect --force - name: Phase A.5 - Create probe recipe @@ -201,7 +225,6 @@ jobs: echo "::group::CCI openssl config.yml" cat /tmp/cci/recipes/openssl/config.yml echo "::endgroup::" - # Fail early if the pinned OPENSSL_VERSION isn't listed in CCI. if ! grep -q "\"${OPENSSL_VERSION}\"" /tmp/cci/recipes/openssl/config.yml; then echo "::error::openssl ${OPENSSL_VERSION} not found in CCI config.yml. Update OPENSSL_VERSION env." exit 1 @@ -210,8 +233,6 @@ jobs: - name: Phase B - Build openssl/${{ env.OPENSSL_VERSION }}@openrv/vfx2024 if: ${{ env.PHASE == 'openssl' }} run: | - # -tf="" skips the CCI test_package step; we only care about - # producing and uploading the binary, not revalidating the recipe. conan create /tmp/cci/recipes/openssl/3.x.x/ \ --version "${OPENSSL_VERSION}" \ --user openrv \ @@ -225,8 +246,7 @@ jobs: - name: Phase C - Upload openssl/${{ env.OPENSSL_VERSION }}@openrv/vfx2024 if: ${{ env.PHASE == 'openssl' }} - run: | - conan upload "openssl/${OPENSSL_VERSION}@openrv/vfx2024" --remote "$REMOTE_NAME" --confirm + run: conan upload "openssl/${OPENSSL_VERSION}@openrv/vfx2024" --remote "$REMOTE_NAME" --confirm - name: Verify server-side listing if: ${{ env.PHASE == 'openssl' }} @@ -234,20 +254,11 @@ jobs: - name: Phase D - Wipe local cache for openssl if: ${{ env.PHASE == 'openssl' }} - run: | - # Remove the just-built package so the install in the next step - # has to pull from the remote. Otherwise conan would use the - # local cache and we would not be exercising the remote. - conan remove "openssl/${OPENSSL_VERSION}@openrv/vfx2024" -c + run: conan remove "openssl/${OPENSSL_VERSION}@openrv/vfx2024" -c - name: Phase D - Round-trip install from ${{ inputs.remote || 'aswftesting' }} if: ${{ env.PHASE == 'openssl' }} run: | - # --build=never makes this step assert "prebuilt binary must - # exist on the remote with the same package_id as the profile - # and options below produce". If Conan would need to build, it - # fails here and we know the upload was incomplete or the - # options do not match what was uploaded. set -o pipefail conan install \ --requires="openssl/${OPENSSL_VERSION}@openrv/vfx2024" \ @@ -256,7 +267,6 @@ jobs: -pr:a "./conan/profiles/${CONAN_PROFILE}" \ -o 'openssl/*:shared=True' \ -o 'openssl/*:no_zlib=True' 2>&1 | tee /tmp/phase_d.log - if grep -qiE "Building from sources|building package" /tmp/phase_d.log; then echo "::error::Phase D regressed - Conan is building instead of downloading." exit 1 @@ -270,9 +280,6 @@ jobs: - name: Phase E - Verify profile rewrites openssl to @openrv/vfx2024 if: ${{ env.PHASE == 'openssl' }} run: | - # conan/profiles/common has [replace_requires] that rewrites - # openssl/* to openssl/${OPENSSL_VERSION}@openrv/vfx2024. Asking - # for plain openssl/3.5.0 should still resolve to the ASWF ref. set -o pipefail conan graph info \ --requires="openssl/3.5.0" \ @@ -280,10 +287,384 @@ jobs: -pr:a "./conan/profiles/${CONAN_PROFILE}" \ -o 'openssl/*:shared=True' \ -o 'openssl/*:no_zlib=True' 2>&1 | tee /tmp/phase_e.log - expected_ref="openssl/${OPENSSL_VERSION}@openrv/vfx2024" if ! grep -qF "$expected_ref" /tmp/phase_e.log; then - echo "::error::Phase E failed - graph does not contain $expected_ref. The profile replace_requires rewrite is not taking effect." + echo "::error::Phase E failed - graph does not contain $expected_ref." exit 1 fi echo "::notice::Phase E success - profile rewrites openssl/* to $expected_ref." + + # --------------------------------------------------------------------------- + # macOS arm64. GitHub-hosted macos-14 runner. Profile: arm64_apple_release. + # --------------------------------------------------------------------------- + macos: + name: "Conan ${{ inputs.phase || 'probe' }} -> macos-arm64 -> ${{ inputs.remote || 'aswftesting' }}" + if: contains(format(',{0},', inputs.platforms || 'rocky8,rocky9,macos,windows'), ',macos,') + runs-on: macos-14 + + env: + CONAN_LOGIN_USERNAME: ${{ secrets.ARTIFACTORY_USER }} + CONAN_PASSWORD: ${{ secrets.ARTIFACTORY_TOKEN }} + CONAN_PROFILE: arm64_apple_release + + steps: + - name: Diagnose secret presence + env: + U: ${{ secrets.ARTIFACTORY_USER }} + T: ${{ secrets.ARTIFACTORY_TOKEN }} + run: | + echo "event: ${GITHUB_EVENT_NAME}" + echo "platform: macos-arm64 (${CONAN_PROFILE})" + echo "ARTIFACTORY_USER length: ${#U}" + echo "ARTIFACTORY_TOKEN length: ${#T}" + + - name: Verify secrets are set + run: | + if [ -z "$CONAN_LOGIN_USERNAME" ] || [ -z "$CONAN_PASSWORD" ]; then + echo "::error::ARTIFACTORY_USER or ARTIFACTORY_TOKEN secret is not set." + exit 1 + fi + + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + submodules: false + + - name: Install CMake + uses: jwlawson/actions-setup-cmake@802fa1a2c4e212495c05bf94dba2704a92a472be # v2 + with: + cmake-version: "${{ env.CMAKE_VERSION }}" + + - name: Install nasm + run: brew install nasm + + - name: Setup Python + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + with: + python-version: "3.11" + + - name: Install Conan 2.x + run: | + python3 -m pip install --upgrade pip + python3 -m pip install "conan>=2.0,<3.0" + conan --version + + - name: Configure Conan remote and authenticate + run: | + conan remote remove "$REMOTE_NAME" 2>/dev/null || true + conan remote add "$REMOTE_NAME" "$REMOTE_URL" --index 0 + conan remote list + conan remote login "$REMOTE_NAME" "$CONAN_LOGIN_USERNAME" -p "$CONAN_PASSWORD" + + - name: Detect default Conan profile + run: conan profile detect --force + + - name: Phase A.5 - Create probe recipe + run: | + mkdir -p /tmp/openrv-probe + cat > /tmp/openrv-probe/conanfile.py <<'PY' + from conan import ConanFile + + class Probe(ConanFile): + name = "openrv-probe" + version = "0.0.1" + package_type = "application" + settings = "os", "arch" + + def package(self): + pass + PY + conan create /tmp/openrv-probe --user openrv --channel test + + - name: Phase A.5 - Upload probe to ${{ inputs.remote || 'aswftesting' }} + id: probe_upload + run: | + set +e + out=$(conan upload "openrv-probe/0.0.1@openrv/test" --remote "$REMOTE_NAME" --confirm 2>&1) + status=$? + echo "$out" + if [ $status -eq 0 ]; then + echo "::notice::Probe upload succeeded (macos)." + else + if echo "$out" | grep -qiE "403|forbidden|unauthorized"; then + echo "::error::Probe upload rejected on macos. Check permissions." + fi + exit $status + fi + + - name: Phase A.5 - Clean up probe from remote + if: always() && steps.probe_upload.outcome == 'success' + continue-on-error: true + run: | + conan remove "openrv-probe/*" -r "$REMOTE_NAME" -c || true + conan remove "openrv-probe/*" -c || true + + - name: Phase B - Clone conan-center-index and verify openssl version + if: ${{ env.PHASE == 'openssl' }} + run: | + git clone --depth 1 --branch master https://github.com/conan-io/conan-center-index.git /tmp/cci + echo "::group::CCI openssl config.yml" + cat /tmp/cci/recipes/openssl/config.yml + echo "::endgroup::" + if ! grep -q "\"${OPENSSL_VERSION}\"" /tmp/cci/recipes/openssl/config.yml; then + echo "::error::openssl ${OPENSSL_VERSION} not found in CCI config.yml." + exit 1 + fi + + - name: Phase B - Build openssl/${{ env.OPENSSL_VERSION }}@openrv/vfx2024 + if: ${{ env.PHASE == 'openssl' }} + run: | + conan create /tmp/cci/recipes/openssl/3.x.x/ \ + --version "${OPENSSL_VERSION}" \ + --user openrv \ + --channel vfx2024 \ + --build=missing \ + -tf="" \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" \ + -o 'openssl/*:shared=True' \ + -o 'openssl/*:no_zlib=True' + conan list "openssl/${OPENSSL_VERSION}@openrv/vfx2024:*" + + - name: Phase C - Upload openssl/${{ env.OPENSSL_VERSION }}@openrv/vfx2024 + if: ${{ env.PHASE == 'openssl' }} + run: conan upload "openssl/${OPENSSL_VERSION}@openrv/vfx2024" --remote "$REMOTE_NAME" --confirm + + - name: Verify server-side listing + if: ${{ env.PHASE == 'openssl' }} + run: conan search "openssl/${OPENSSL_VERSION}@openrv/vfx2024" -r "$REMOTE_NAME" + + - name: Phase D - Wipe local cache for openssl + if: ${{ env.PHASE == 'openssl' }} + run: conan remove "openssl/${OPENSSL_VERSION}@openrv/vfx2024" -c + + - name: Phase D - Round-trip install from ${{ inputs.remote || 'aswftesting' }} + if: ${{ env.PHASE == 'openssl' }} + run: | + set -o pipefail + conan install \ + --requires="openssl/${OPENSSL_VERSION}@openrv/vfx2024" \ + -r "$REMOTE_NAME" \ + --build=never \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" \ + -o 'openssl/*:shared=True' \ + -o 'openssl/*:no_zlib=True' 2>&1 | tee /tmp/phase_d.log + if grep -qiE "Building from sources|building package" /tmp/phase_d.log; then + echo "::error::Phase D regressed on macos - Conan is building instead of downloading." + exit 1 + fi + if ! grep -qiE "downloaded|Already installed" /tmp/phase_d.log; then + echo "::error::Phase D log does not show a download on macos." + exit 1 + fi + echo "::notice::Phase D success on macos." + + - name: Phase E - Verify profile rewrites openssl to @openrv/vfx2024 + if: ${{ env.PHASE == 'openssl' }} + run: | + set -o pipefail + conan graph info \ + --requires="openssl/3.5.0" \ + -r "$REMOTE_NAME" \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" \ + -o 'openssl/*:shared=True' \ + -o 'openssl/*:no_zlib=True' 2>&1 | tee /tmp/phase_e.log + expected_ref="openssl/${OPENSSL_VERSION}@openrv/vfx2024" + if ! grep -qF "$expected_ref" /tmp/phase_e.log; then + echo "::error::Phase E failed on macos - graph missing $expected_ref." + exit 1 + fi + echo "::notice::Phase E success on macos." + + # --------------------------------------------------------------------------- + # Windows x86_64. windows-2022 + MSVC + MSYS2. Profile: x86_64_windows. + # --------------------------------------------------------------------------- + windows: + name: "Conan ${{ inputs.phase || 'probe' }} -> windows-x86_64 -> ${{ inputs.remote || 'aswftesting' }}" + if: contains(format(',{0},', inputs.platforms || 'rocky8,rocky9,macos,windows'), ',windows,') + runs-on: windows-2022 + + env: + CONAN_LOGIN_USERNAME: ${{ secrets.ARTIFACTORY_USER }} + CONAN_PASSWORD: ${{ secrets.ARTIFACTORY_TOKEN }} + CONAN_PROFILE: x86_64_windows + + defaults: + run: + shell: msys2 {0} + + steps: + - name: Diagnose secret presence + shell: bash + env: + U: ${{ secrets.ARTIFACTORY_USER }} + T: ${{ secrets.ARTIFACTORY_TOKEN }} + run: | + echo "event: ${GITHUB_EVENT_NAME}" + echo "platform: windows-x86_64 (${CONAN_PROFILE})" + echo "ARTIFACTORY_USER length: ${#U}" + echo "ARTIFACTORY_TOKEN length: ${#T}" + + - name: Verify secrets are set + shell: bash + run: | + if [ -z "$CONAN_LOGIN_USERNAME" ] || [ -z "$CONAN_PASSWORD" ]; then + echo "::error::ARTIFACTORY_USER or ARTIFACTORY_TOKEN secret is not set." + exit 1 + fi + + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + submodules: false + + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + cache: false + install: >- + mingw-w64-x86_64-toolchain + mingw-w64-x86_64-cmake + mingw-w64-x86_64-make + mingw-w64-x86_64-python + mingw-w64-x86_64-python-pip + nasm + perl + make + git + + - name: Install Conan 2.x (inside msys2) + run: | + python -m pip install --upgrade pip + python -m pip install "conan>=2.0,<3.0" + conan --version + + - name: Configure Conan remote and authenticate + run: | + conan remote remove "$REMOTE_NAME" 2>/dev/null || true + conan remote add "$REMOTE_NAME" "$REMOTE_URL" --index 0 + conan remote list + conan remote login "$REMOTE_NAME" "$CONAN_LOGIN_USERNAME" -p "$CONAN_PASSWORD" + + - name: Detect default Conan profile + run: conan profile detect --force + + - name: Phase A.5 - Create probe recipe + run: | + mkdir -p /tmp/openrv-probe + cat > /tmp/openrv-probe/conanfile.py <<'PY' + from conan import ConanFile + + class Probe(ConanFile): + name = "openrv-probe" + version = "0.0.1" + package_type = "application" + settings = "os", "arch" + + def package(self): + pass + PY + conan create /tmp/openrv-probe --user openrv --channel test + + - name: Phase A.5 - Upload probe to ${{ inputs.remote || 'aswftesting' }} + id: probe_upload + run: | + set +e + out=$(conan upload "openrv-probe/0.0.1@openrv/test" --remote "$REMOTE_NAME" --confirm 2>&1) + status=$? + echo "$out" + if [ $status -eq 0 ]; then + echo "::notice::Probe upload succeeded (windows)." + else + if echo "$out" | grep -qiE "403|forbidden|unauthorized"; then + echo "::error::Probe upload rejected on windows. Check permissions." + fi + exit $status + fi + + - name: Phase A.5 - Clean up probe from remote + if: always() && steps.probe_upload.outcome == 'success' + continue-on-error: true + run: | + conan remove "openrv-probe/*" -r "$REMOTE_NAME" -c || true + conan remove "openrv-probe/*" -c || true + + - name: Phase B - Clone conan-center-index and verify openssl version + if: ${{ env.PHASE == 'openssl' }} + run: | + git clone --depth 1 --branch master https://github.com/conan-io/conan-center-index.git /tmp/cci + echo "::group::CCI openssl config.yml" + cat /tmp/cci/recipes/openssl/config.yml + echo "::endgroup::" + if ! grep -q "\"${OPENSSL_VERSION}\"" /tmp/cci/recipes/openssl/config.yml; then + echo "::error::openssl ${OPENSSL_VERSION} not found in CCI config.yml." + exit 1 + fi + + - name: Phase B - Build openssl/${{ env.OPENSSL_VERSION }}@openrv/vfx2024 + if: ${{ env.PHASE == 'openssl' }} + run: | + conan create /tmp/cci/recipes/openssl/3.x.x/ \ + --version "${OPENSSL_VERSION}" \ + --user openrv \ + --channel vfx2024 \ + --build=missing \ + -tf="" \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" \ + -o 'openssl/*:shared=True' \ + -o 'openssl/*:no_zlib=True' + conan list "openssl/${OPENSSL_VERSION}@openrv/vfx2024:*" + + - name: Phase C - Upload openssl/${{ env.OPENSSL_VERSION }}@openrv/vfx2024 + if: ${{ env.PHASE == 'openssl' }} + run: conan upload "openssl/${OPENSSL_VERSION}@openrv/vfx2024" --remote "$REMOTE_NAME" --confirm + + - name: Verify server-side listing + if: ${{ env.PHASE == 'openssl' }} + run: conan search "openssl/${OPENSSL_VERSION}@openrv/vfx2024" -r "$REMOTE_NAME" + + - name: Phase D - Wipe local cache for openssl + if: ${{ env.PHASE == 'openssl' }} + run: conan remove "openssl/${OPENSSL_VERSION}@openrv/vfx2024" -c + + - name: Phase D - Round-trip install from ${{ inputs.remote || 'aswftesting' }} + if: ${{ env.PHASE == 'openssl' }} + run: | + set -o pipefail + conan install \ + --requires="openssl/${OPENSSL_VERSION}@openrv/vfx2024" \ + -r "$REMOTE_NAME" \ + --build=never \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" \ + -o 'openssl/*:shared=True' \ + -o 'openssl/*:no_zlib=True' 2>&1 | tee /tmp/phase_d.log + if grep -qiE "Building from sources|building package" /tmp/phase_d.log; then + echo "::error::Phase D regressed on windows - Conan is building instead of downloading." + exit 1 + fi + if ! grep -qiE "downloaded|Already installed" /tmp/phase_d.log; then + echo "::error::Phase D log does not show a download on windows." + exit 1 + fi + echo "::notice::Phase D success on windows." + + - name: Phase E - Verify profile rewrites openssl to @openrv/vfx2024 + if: ${{ env.PHASE == 'openssl' }} + run: | + set -o pipefail + conan graph info \ + --requires="openssl/3.5.0" \ + -r "$REMOTE_NAME" \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" \ + -o 'openssl/*:shared=True' \ + -o 'openssl/*:no_zlib=True' 2>&1 | tee /tmp/phase_e.log + expected_ref="openssl/${OPENSSL_VERSION}@openrv/vfx2024" + if ! grep -qF "$expected_ref" /tmp/phase_e.log; then + echo "::error::Phase E failed on windows - graph missing $expected_ref." + exit 1 + fi + echo "::notice::Phase E success on windows." From e49ce8e17392b9de89843e976e3b5f7754c38334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Thu, 23 Apr 2026 10:39:56 -0400 Subject: [PATCH 10/20] openssl test all platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/conan-upload-test.yml | 47 ++++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/.github/workflows/conan-upload-test.yml b/.github/workflows/conan-upload-test.yml index 64f6df0eb..b3982e2c8 100644 --- a/.github/workflows/conan-upload-test.yml +++ b/.github/workflows/conan-upload-test.yml @@ -54,7 +54,10 @@ env: CMAKE_VERSION: "3.31.6" # inputs.* is only populated for workflow_dispatch. For push / PR # triggers these are empty; each job applies its own fallback. - PHASE: ${{ inputs.phase || 'probe' }} + # TEMP: phase default is 'openssl' while dispatch is unavailable and + # the cross-platform openssl run is being validated. Flip back to + # 'probe' once the four-platform run passes. + PHASE: ${{ inputs.phase || 'openssl' }} REMOTE_NAME: ${{ inputs.remote || 'aswftesting' }} REMOTE_URL: ${{ inputs.remote == 'aswf' && 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan' || 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan-dev' }} PLATFORMS: ${{ inputs.platforms || 'rocky8,rocky9,macos,windows' }} @@ -211,12 +214,18 @@ jobs: exit $status fi - - name: Phase A.5 - Clean up probe from remote + - name: Phase A.5 - Clean up probe (local + best-effort remote) if: always() && steps.probe_upload.outcome == 'success' - continue-on-error: true run: | - conan remove "openrv-probe/*" -r "$REMOTE_NAME" -c || true - conan remove "openrv-probe/*" -c || true + # Remote cleanup typically fails 403 on LF Artifactory because + # the OpenRV token has upload-only rights on @openrv/*. Treat + # as expected; an admin can clean the probe ref periodically. + if conan remove "openrv-probe/*" -r "$REMOTE_NAME" -c 2>/dev/null; then + echo "::notice::Remote probe cleaned from $REMOTE_NAME." + else + echo "::notice::Remote probe cleanup returned non-zero (expected for upload-only tokens). Leaving openrv-probe on $REMOTE_NAME." + fi + conan remove "openrv-probe/*" -c 2>/dev/null || true - name: Phase B - Clone conan-center-index and verify openssl version if: ${{ env.PHASE == 'openssl' }} @@ -391,12 +400,18 @@ jobs: exit $status fi - - name: Phase A.5 - Clean up probe from remote + - name: Phase A.5 - Clean up probe (local + best-effort remote) if: always() && steps.probe_upload.outcome == 'success' - continue-on-error: true run: | - conan remove "openrv-probe/*" -r "$REMOTE_NAME" -c || true - conan remove "openrv-probe/*" -c || true + # Remote cleanup typically fails 403 on LF Artifactory because + # the OpenRV token has upload-only rights on @openrv/*. Treat + # as expected; an admin can clean the probe ref periodically. + if conan remove "openrv-probe/*" -r "$REMOTE_NAME" -c 2>/dev/null; then + echo "::notice::Remote probe cleaned from $REMOTE_NAME." + else + echo "::notice::Remote probe cleanup returned non-zero (expected for upload-only tokens). Leaving openrv-probe on $REMOTE_NAME." + fi + conan remove "openrv-probe/*" -c 2>/dev/null || true - name: Phase B - Clone conan-center-index and verify openssl version if: ${{ env.PHASE == 'openssl' }} @@ -586,12 +601,18 @@ jobs: exit $status fi - - name: Phase A.5 - Clean up probe from remote + - name: Phase A.5 - Clean up probe (local + best-effort remote) if: always() && steps.probe_upload.outcome == 'success' - continue-on-error: true run: | - conan remove "openrv-probe/*" -r "$REMOTE_NAME" -c || true - conan remove "openrv-probe/*" -c || true + # Remote cleanup typically fails 403 on LF Artifactory because + # the OpenRV token has upload-only rights on @openrv/*. Treat + # as expected; an admin can clean the probe ref periodically. + if conan remove "openrv-probe/*" -r "$REMOTE_NAME" -c 2>/dev/null; then + echo "::notice::Remote probe cleaned from $REMOTE_NAME." + else + echo "::notice::Remote probe cleanup returned non-zero (expected for upload-only tokens). Leaving openrv-probe on $REMOTE_NAME." + fi + conan remove "openrv-probe/*" -c 2>/dev/null || true - name: Phase B - Clone conan-center-index and verify openssl version if: ${{ env.PHASE == 'openssl' }} From 4be70dc2071c7ac4a068f8d22711053628be3ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Thu, 23 Apr 2026 20:10:15 -0400 Subject: [PATCH 11/20] test approach to upload packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/conan-upload-deps.yml | 282 ++++++++++++++++++++++++ .github/workflows/conan.yml | 5 + conan/packages.yml | 130 +++++++++++ conan/profiles/common | 34 ++- 4 files changed, 446 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/conan-upload-deps.yml create mode 100644 conan/packages.yml diff --git a/.github/workflows/conan-upload-deps.yml b/.github/workflows/conan-upload-deps.yml new file mode 100644 index 000000000..b32fa895d --- /dev/null +++ b/.github/workflows/conan-upload-deps.yml @@ -0,0 +1,282 @@ +name: Conan Upload Deps (@openrv/vfx2024) + +# Batch-builds the non-openssl deps declared in conan/packages.yml and +# uploads them under @openrv/vfx2024 to the ASWF Conan remote. Mirrors +# the phase pattern already proven in .github/workflows/conan-upload-test.yml +# for openssl, but driven by packages.yml so adding or bumping a dep is +# a one-file change. +# +# Scope (this iteration): +# - Rocky 8 profile only (x86_64_rocky8). +# - Uploads to aswftesting by default. +# - pcre2 is windows_only and skipped here; picked up in the cross-platform +# follow-up (Phase 6 of the plan). + +on: + push: + branches: + - main + # Temporary: auto-run on the Conan-ASWF test branch while manual + # workflow dispatch is not available. Remove once testing is done. + - find-fork-test-aswf + + pull_request: + + workflow_dispatch: + inputs: + remote: + description: "Target Conan remote" + required: true + default: "aswftesting" + type: choice + options: + - aswftesting + - aswf + only: + description: "Single package name to run (empty = all)" + required: false + default: "" + +env: + REMOTE_NAME: ${{ inputs.remote || 'aswftesting' }} + REMOTE_URL: ${{ inputs.remote == 'aswf' && 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan' || 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan-dev' }} + CMAKE_VERSION: "3.31.6" + CONAN_PROFILE: x86_64_rocky8 + +jobs: + # --------------------------------------------------------------------------- + # Reads conan/packages.yml, filters out windows_only entries and optionally + # narrows to a single package via the `only` input. Emits a JSON array of + # matrix rows consumed by build-upload. + # --------------------------------------------------------------------------- + prepare-matrix: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.gen.outputs.matrix }} + count: ${{ steps.gen.outputs.count }} + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + with: + python-version: "3.11" + + - name: Install PyYAML + run: python3 -m pip install --user pyyaml + + - name: Generate matrix from conan/packages.yml + id: gen + env: + ONLY: ${{ inputs.only || '' }} + run: | + python3 - <<'PY' + import json, os, sys, yaml + + cfg = yaml.safe_load(open("conan/packages.yml")) + only = os.environ.get("ONLY", "").strip() + rows = [] + for dep in cfg["deps"]: + if dep.get("windows_only"): + continue + if only and dep["name"] != only: + continue + opts = dep.get("options") or {} + # Emit options as a flat list of tokens: ["-o", "foo=bar", ...]. + # The consuming job parses this JSON into a bash array to avoid + # shell-glob expansion on `*` in option patterns. + flags = [] + for k, v in opts.items(): + flags.append("-o") + flags.append(f"{k}={v}") + rows.append({ + "name": dep["name"], + "version": dep["version"], + "cci_folder": dep["cci_folder"], + "options_json": json.dumps(flags), + }) + + if only and not rows: + print(f"::error::--only={only} matched no entry in conan/packages.yml", file=sys.stderr) + sys.exit(1) + + payload = json.dumps(rows) + print(f"Matrix rows ({len(rows)}):") + for r in rows: + print(f" {r['name']}/{r['version']} ({r['cci_folder']})") + + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"matrix={payload}\n") + f.write(f"count={len(rows)}\n") + PY + + # --------------------------------------------------------------------------- + # One matrix row per package. Rocky 8 container, same bootstrap pattern as + # conan-upload-test.yml (base packages, gcc-toolset-11, Kitware CMake, + # Conan 2.x, remote add, login). Each row exports the CCI recipe under + # @openrv/vfx2024, builds, uploads, and asserts server-side listing. + # --------------------------------------------------------------------------- + build-upload: + name: "Conan deps: ${{ matrix.name }}/${{ matrix.version }} -> ${{ inputs.remote || 'aswftesting' }}" + needs: prepare-matrix + if: needs.prepare-matrix.outputs.count != '0' + runs-on: ubuntu-latest + container: + image: amd64/rockylinux:8 + + strategy: + fail-fast: false + max-parallel: 8 + matrix: + include: ${{ fromJSON(needs.prepare-matrix.outputs.matrix) }} + + env: + CONAN_LOGIN_USERNAME: ${{ secrets.ARTIFACTORY_USER }} + CONAN_PASSWORD: ${{ secrets.ARTIFACTORY_TOKEN }} + + steps: + - name: Verify secrets are set + run: | + if [ -z "$CONAN_LOGIN_USERNAME" ] || [ -z "$CONAN_PASSWORD" ]; then + echo "::error::ARTIFACTORY_USER or ARTIFACTORY_TOKEN secret is not set on this repo." + exit 1 + fi + + - name: Install base system packages + # VFX Reference Platform CY2024 mandates Python 3.11. Rocky 8's + # default `python3` is 3.6.8, which is too old for meson (>=3.7 + # required), so dav1d/libjpeg-turbo/etc. fail when Conan builds + # meson from source under the default interpreter. Install + # python3.11 from AppStream and expose it as the default + # `python3` / `pip3` via /usr/local/bin so every subsequent step + # (Conan install, recipe build() calls, meson) runs on 3.11. + run: | + dnf install -y epel-release + dnf config-manager --set-enabled powertools devel + dnf groupinstall "Development Tools" -y + dnf install -y which findutils git python3.11 python3.11-pip perl perl-IPC-Cmd perl-Digest-SHA nasm make + ln -sf /usr/bin/python3.11 /usr/local/bin/python3 + ln -sf /usr/bin/pip3.11 /usr/local/bin/pip3 + python3 --version + dnf clean all + + - name: Install gcc-toolset-11 + run: | + for i in 1 2 3 4 5; do + dnf install -y gcc-toolset-11-toolchain && break + echo "attempt $i failed, retrying in 5s"; sleep 5 + done + + - name: Enable gcc-toolset-11 + run: | + source /opt/rh/gcc-toolset-11/enable + echo "/opt/rh/gcc-toolset-11/root/usr/bin" >> $GITHUB_PATH + echo "CC=/opt/rh/gcc-toolset-11/root/usr/bin/gcc" >> $GITHUB_ENV + echo "CXX=/opt/rh/gcc-toolset-11/root/usr/bin/g++" >> $GITHUB_ENV + gcc --version + + - name: Install CMake + # Install under /opt so the subsequent actions/checkout step does not + # wipe it (checkout cleans the workspace by default). Then symlink + # into /usr/local/bin so Conan's self.run(..., env="conanbuild"), + # which can isolate PATH via the generated buildenv.sh, still finds + # cmake when recipe build() methods invoke it. + run: | + curl -SL -o /tmp/cmake.tar.gz "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz" + mkdir -p /opt + tar -xzf /tmp/cmake.tar.gz -C /opt + ln -sf "/opt/cmake-${CMAKE_VERSION}-linux-x86_64/bin/cmake" /usr/local/bin/cmake + ln -sf "/opt/cmake-${CMAKE_VERSION}-linux-x86_64/bin/ctest" /usr/local/bin/ctest + ln -sf "/opt/cmake-${CMAKE_VERSION}-linux-x86_64/bin/cpack" /usr/local/bin/cpack + echo "/opt/cmake-${CMAKE_VERSION}-linux-x86_64/bin" >> $GITHUB_PATH + cmake --version + + - name: Install Conan 2.x + run: | + python3 -m pip install --upgrade pip + python3 -m pip install "conan>=2.0,<3.0" + conan --version + + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + submodules: false + + - name: Mark repo as safe git directory + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + + - name: Configure Conan remote and authenticate + run: | + conan remote remove "$REMOTE_NAME" 2>/dev/null || true + conan remote add "$REMOTE_NAME" "$REMOTE_URL" --index 0 + conan remote list + conan remote login "$REMOTE_NAME" "$CONAN_LOGIN_USERNAME" -p "$CONAN_PASSWORD" + + - name: Detect default Conan profile + run: conan profile detect --force + + - name: Clone conan-center-index + run: git clone --depth 1 --branch master https://github.com/conan-io/conan-center-index.git /tmp/cci + + - name: Verify CCI recipe folder exists + run: | + DIR="/tmp/cci/recipes/${{ matrix.name }}/${{ matrix.cci_folder }}" + if [ ! -d "$DIR" ]; then + echo "::error::Recipe folder $DIR not found. Siblings:" + ls -1 "/tmp/cci/recipes/${{ matrix.name }}/" || true + exit 1 + fi + echo "Using recipe: $DIR" + + - name: Verify pinned version is available in CCI + run: | + CONFIG="/tmp/cci/recipes/${{ matrix.name }}/config.yml" + echo "::group::${{ matrix.name }} config.yml" + cat "$CONFIG" + echo "::endgroup::" + if ! grep -q "\"${{ matrix.version }}\"" "$CONFIG"; then + echo "::error::${{ matrix.name }}/${{ matrix.version }} not listed in $CONFIG. Version may have been rotated out of CCI; update conan/packages.yml." + exit 1 + fi + + - name: Export recipe with user/channel + run: | + conan export "/tmp/cci/recipes/${{ matrix.name }}/${{ matrix.cci_folder }}/" \ + --version "${{ matrix.version }}" \ + --user openrv \ + --channel vfx2024 + + - name: Build ${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024 + env: + OPTIONS_JSON: ${{ matrix.options_json }} + # sh-compatible: emit each option token NUL-terminated from Python, + # pipe to xargs -0 which appends them to the conan argv. Avoids shell + # glob expansion on `*` in option patterns and handles values that + # contain spaces (e.g., boost's extra_b2_flags). + # + # The extra `--build=/*` patterns force Conan to rebuild + # build-time tool_requires from source on the Rocky 8 runner rather + # than pulling prebuilt CCI binaries. Those prebuilts are compiled + # on newer hosts (glibc >= 2.32) and fail to launch against Rocky 8's + # glibc 2.28 (e.g., boost's b2/4.10.1, dav1d's meson/1.4.0 + + # nasm/2.16.01, libjpeg-turbo's nasm). Rebuilding locally also keeps + # the toolchain homogeneous per VFX Reference Platform CY2024 + # ("same compiler for a given OS"). Extend this list if a new + # tool surfaces a `GLIBC_2.xx not found` error. + run: | + python3 -c "import json,sys; sys.stdout.write(''.join(t + '\0' for t in json.loads(sys.argv[1])))" "$OPTIONS_JSON" \ + | xargs -0 conan install \ + --requires="${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024" \ + --build=missing \ + --build="b2/*" \ + --build="meson/*" \ + --build="nasm/*" \ + -pr:a "./conan/profiles/${CONAN_PROFILE}" + conan list "${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024:*" + + - name: Upload ${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024 + run: conan upload "${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024" --remote "$REMOTE_NAME" --confirm + + - name: Verify server-side listing + run: conan search "${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024" -r "$REMOTE_NAME" diff --git a/.github/workflows/conan.yml b/.github/workflows/conan.yml index 72750cf20..c37f78788 100644 --- a/.github/workflows/conan.yml +++ b/.github/workflows/conan.yml @@ -331,6 +331,11 @@ jobs: $CONAN_EXECUTABLE export openrvcore-conanfile.py - name: Build OpenRV dependencies + # openexr (and every other dep covered by [replace_requires] in + # conan/profiles/common) now resolves to @openrv/vfx2024 and is + # pulled prebuilt from the ASWF remote on Rocky 8, built on the + # matching toolchain. The earlier Rocky 8-specific `--build=openexr/*` + # workaround is no longer needed. run: | # Rocky 8: force local rebuild of select packages whose Conan Center # prebuilts target a newer glibc / libstdc++ than Rocky 8 provides. diff --git a/conan/packages.yml b/conan/packages.yml new file mode 100644 index 000000000..477c2898d --- /dev/null +++ b/conan/packages.yml @@ -0,0 +1,130 @@ +# OpenRV Conan dependencies published under @openrv/vfx2024. +# +# Single source of truth consumed by .github/workflows/conan-upload-deps.yml. +# Each entry mirrors openrvcore-conanfile.py:63-128 (name, version, options +# on conan create). The workflow builds each on x86_64_rocky8 and uploads +# to the ASWF Conan remote (aswftesting by default). +# +# Fields: +# name - Conan package name (matches CCI recipe folder). +# version - Pinned version; must be listed in CCI config.yml. +# cci_folder - Subfolder under recipes// in conan-center-index. +# Most are "all"; a few like openssl use "3.x.x". +# options - Map of Conan option -> value. Passed as -o flags on +# conan install. Pattern strings like "foo/*:shared" match +# the install --requires ref. +# windows_only - Optional. If true, this entry is filtered out when the +# workflow runs on a Linux or macOS platform. + +deps: + - name: zlib + version: "1.3.1" + cci_folder: all + options: + "zlib/*:shared": "True" + + - name: libatomic_ops + version: "7.10.0" + cci_folder: all + options: + "libatomic_ops/*:shared": "False" + + - name: libwebp + # openrvcore-conanfile.py:69 pins 1.2.1 because libwebp >=1.3.0 adds + # sharpyuv and causes issues with OIIO. CCI rotated 1.2.1 out; 1.2.4 + # is the closest available that remains pre-1.3.0. + version: "1.2.4" + cci_folder: all + options: + "libwebp/*:shared": "False" + + - name: dav1d + version: "1.5.3" + cci_folder: all + options: + "dav1d/*:shared": "True" + + - name: libjpeg-turbo + # 2.1.4 rotated out of CCI; 2.1.5 is the closest 2.1.x available. + # Avoiding 3.x to prevent ABI surprises against libraw/openjph. + version: "2.1.5" + cci_folder: all + options: + "libjpeg-turbo/*:shared": "True" + + - name: boost + # The recipe revision pin #7053477b271b8c39e046f784405b402f from + # openrvcore-conanfile.py:87 may be unresolvable on CCI master. + # Workflow strips any #rrev suffix before conan create; the produced + # @openrv/vfx2024 ref gets its own revision. + version: "1.82.0" + cci_folder: all + options: + "boost/*:shared": "True" + "boost/*:extra_b2_flags": "-d+0 -s NO_LZMA=1" + + - name: imath + # 3.2.1 rotated; 3.2.2 is a patch bump within 3.2.x. + version: "3.2.2" + cci_folder: all + options: + "imath/*:shared": "True" + + - name: libdeflate + version: "1.25" + cci_folder: all + options: + "libdeflate/*:shared": "True" + + - name: openexr + # 3.2.5 rotated; 3.2.8 is a patch bump within 3.2.x. + # Avoiding 3.3/3.4 because they would require realigning imath. + # openexr splits recipes by major: 2.x and 3.x (no "all"). + version: "3.2.8" + cci_folder: "3.x" + options: + "openexr/*:shared": "True" + + - name: libpng + # 1.6.55 rotated; 1.6.58 is a patch bump within 1.6.x. + version: "1.6.58" + cci_folder: all + options: + "libpng/*:shared": "True" + + - name: openjpeg + version: "2.5.4" + cci_folder: all + options: + "openjpeg/*:shared": "True" + + - name: libraw + # 0.21.1 rotated; 0.21.2 is a patch bump within 0.21.x. + # 0.21.5b has a beta suffix, avoided. + version: "0.21.2" + cci_folder: all + options: + "libraw/*:shared": "True" + "libraw/*:with_jpeg": "libjpeg-turbo" + "libraw/*:with_jasper": "False" + + - name: openjph + # 0.26.3 rotated; 0.27.0 is the only remaining version in CCI. + # Minor bump; validate CMake target name compatibility. + version: "0.27.0" + cci_folder: all + options: + "openjph/*:shared": "True" + "openjph/*:with_tiff": "False" + + - name: pcre2 + version: "10.44" + cci_folder: all + windows_only: true + options: + "pcre2/*:shared": "True" + "pcre2/*:with_zlib": "False" + "pcre2/*:with_bzip2": "False" + "pcre2/*:support_jit": "False" + "pcre2/*:build_pcre2_16": "False" + "pcre2/*:build_pcre2_32": "False" diff --git a/conan/profiles/common b/conan/profiles/common index 2188b06eb..a8d3ee511 100644 --- a/conan/profiles/common +++ b/conan/profiles/common @@ -1,8 +1,32 @@ -# Common settings shared across all OpenRV profiles +# Common settings shared across all OpenRV profiles. +# +# Redirect every OpenRV-managed dependency to the prebuilt binary published +# under @openrv/vfx2024 on the ASWF Conan remote (aswf-conan-dev for testing, +# aswf-conan for production). Consumers must have one of those remotes +# configured before running `conan install`. The versions below track +# conan/packages.yml, which is the single source of truth for what the +# conan-upload-deps.yml workflow builds and uploads. +# +# With RV_DEPS_*_VERSION_MATCH=MINIMUM set in openrvcore-conanfile.py, these +# refs may be newer than what the conanfile pins; CMake's find_package will +# still accept them. replace_requires runs before force=True, so the bare +# version pins in the conanfile effectively become cosmetic for anything +# covered here. [replace_requires] -# openssl resolves to the prebuilt binary hosted under @openrv/vfx2024 -# on the ASWF Conan remote (aswf-conan-dev / aswf-conan). Consumers must -# have one of those remotes configured to resolve this reference. +zlib/*: zlib/1.3.1@openrv/vfx2024 +libatomic_ops/*: libatomic_ops/7.10.0@openrv/vfx2024 +libwebp/*: libwebp/1.2.4@openrv/vfx2024 +dav1d/*: dav1d/1.5.3@openrv/vfx2024 +libjpeg/*: libjpeg-turbo/2.1.5@openrv/vfx2024 +libjpeg-turbo/*: libjpeg-turbo/2.1.5@openrv/vfx2024 +boost/*: boost/1.82.0@openrv/vfx2024 +imath/*: imath/3.2.2@openrv/vfx2024 +libdeflate/*: libdeflate/1.25@openrv/vfx2024 +openexr/*: openexr/3.2.8@openrv/vfx2024 +libpng/*: libpng/1.6.58@openrv/vfx2024 +openjpeg/*: openjpeg/2.5.4@openrv/vfx2024 +libraw/*: libraw/0.21.2@openrv/vfx2024 +openjph/*: openjph/0.27.0@openrv/vfx2024 +pcre2/*: pcre2/10.44@openrv/vfx2024 openssl/*: openssl/3.5.6@openrv/vfx2024 -libjpeg/*: libjpeg-turbo/2.1.4 From 94203a73a422e8c35a6331e275fce8350822355c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Tue, 5 May 2026 08:28:40 -0400 Subject: [PATCH 12/20] version update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- conan/packages.yml | 10 +++------- openrvcore-conanfile.py | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/conan/packages.yml b/conan/packages.yml index 477c2898d..82eab6eb6 100644 --- a/conan/packages.yml +++ b/conan/packages.yml @@ -18,7 +18,7 @@ deps: - name: zlib - version: "1.3.1" + version: "1.3.2" cci_folder: all options: "zlib/*:shared": "True" @@ -64,8 +64,7 @@ deps: "boost/*:extra_b2_flags": "-d+0 -s NO_LZMA=1" - name: imath - # 3.2.1 rotated; 3.2.2 is a patch bump within 3.2.x. - version: "3.2.2" + version: "3.1.12" cci_folder: all options: "imath/*:shared": "True" @@ -77,10 +76,7 @@ deps: "libdeflate/*:shared": "True" - name: openexr - # 3.2.5 rotated; 3.2.8 is a patch bump within 3.2.x. - # Avoiding 3.3/3.4 because they would require realigning imath. - # openexr splits recipes by major: 2.x and 3.x (no "all"). - version: "3.2.8" + version: "3.3.6" cci_folder: "3.x" options: "openexr/*:shared": "True" diff --git a/openrvcore-conanfile.py b/openrvcore-conanfile.py index 361c2e740..fdb69fade 100644 --- a/openrvcore-conanfile.py +++ b/openrvcore-conanfile.py @@ -61,7 +61,7 @@ def build_requirements(self): self.tool_requires("cmake/3.31.8") def requirements(self): - self.requires("zlib/1.3.1", force=True, options={"shared": True}) + self.requires("zlib/1.3.2", force=True, options={"shared": True}) self.requires("libatomic_ops/7.10.0", options={"shared": False}) From 60f2cc461e4834f75308bd83638644af173782b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Tue, 5 May 2026 10:52:53 -0400 Subject: [PATCH 13/20] Split common and cy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .github/workflows/conan-upload-deps.yml | 468 +++++++++++++++++------- conan/packages.yml | 23 +- conan/profiles/common | 40 +- 3 files changed, 380 insertions(+), 151 deletions(-) diff --git a/.github/workflows/conan-upload-deps.yml b/.github/workflows/conan-upload-deps.yml index b32fa895d..e144d648d 100644 --- a/.github/workflows/conan-upload-deps.yml +++ b/.github/workflows/conan-upload-deps.yml @@ -1,16 +1,39 @@ -name: Conan Upload Deps (@openrv/vfx2024) - -# Batch-builds the non-openssl deps declared in conan/packages.yml and -# uploads them under @openrv/vfx2024 to the ASWF Conan remote. Mirrors -# the phase pattern already proven in .github/workflows/conan-upload-test.yml -# for openssl, but driven by packages.yml so adding or bumping a dep is -# a one-file change. +name: Conan Upload Deps + +# Batch-builds OpenRV's Conan deps declared in conan/packages.yml and +# uploads them to the ASWF Conan remote. Year-specific deps (CY2025.cmake) +# are published under @openrv/vfx2025; year-independent deps (CYCOMMON.cmake) +# under @openrv/common. Channel is driven by the `channel` field in +# packages.yml. Mirrors the phase pattern already proven in +# conan-upload-test.yml (openssl) and covers every platform in conan.yml's +# build matrix: +# +# rocky8 - amd64/rockylinux:8 + gcc-toolset-11 (profile x86_64_rocky8) +# macos - macos-14 (arm64) + Apple clang (profile arm64_apple_release) +# windows - windows-2022 + MSVC + MSYS2 (profile x86_64_windows) +# +# Rocky 9 is intentionally NOT uploaded. Its Conan profile is identical +# to Rocky 8's (os=Linux, compiler=gcc/11/libstdc++11), so binaries +# uploaded from a Rocky 9 runner share the same package_id as Rocky 8 +# but carry newer glibc / libstdc++ symbol requirements and break Rocky +# 8 consumers at link time. VFX CY2025 defines one Linux target (glibc +# 2.28 = Rocky 8); Rocky 9 consumes the Rocky 8 binaries, which are +# forward-compatible. +# +# Platform binaries live under the same @openrv/ ref; Conan keeps +# them separate by package_id derived from settings. # -# Scope (this iteration): -# - Rocky 8 profile only (x86_64_rocky8). -# - Uploads to aswftesting by default. -# - pcre2 is windows_only and skipped here; picked up in the cross-platform -# follow-up (Phase 6 of the plan). +# Each matrix cell: +# 1. Exports every packages.yml recipe under @openrv/ so that +# replace_requires in conan/profiles/common can resolve transitive +# deps locally. +# 2. Runs `conan install --requires=@openrv/ --build=missing` +# with the full option union across packages.yml, plus forced local +# rebuild of glibc-sensitive host tools (b2, meson, nasm) to defend +# against CCI prebuilts built on newer hosts. +# 3. Uploads every @openrv/* ref in cache (target + transitives). +# +# pcre2 is windows_only and is only present in the Windows matrix. on: push: @@ -36,24 +59,32 @@ on: description: "Single package name to run (empty = all)" required: false default: "" + platforms: + description: "Comma-separated subset of rocky8,macos,windows (empty = all)" + required: false + default: "rocky8,macos,windows" env: REMOTE_NAME: ${{ inputs.remote || 'aswftesting' }} REMOTE_URL: ${{ inputs.remote == 'aswf' && 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan' || 'https://linuxfoundation.jfrog.io/artifactory/api/conan/aswf-conan-dev' }} CMAKE_VERSION: "3.31.6" - CONAN_PROFILE: x86_64_rocky8 + PYTHON_VERSION: "3.11" + PLATFORMS: ${{ inputs.platforms || 'rocky8,macos,windows' }} jobs: # --------------------------------------------------------------------------- - # Reads conan/packages.yml, filters out windows_only entries and optionally - # narrows to a single package via the `only` input. Emits a JSON array of - # matrix rows consumed by build-upload. + # Reads conan/packages.yml and emits two matrices: + # matrix_nonwindows - excludes windows_only entries (Linux + macOS jobs) + # matrix_windows - all entries, including windows_only (Windows job) + # Optionally narrows to a single package via the `only` input. # --------------------------------------------------------------------------- prepare-matrix: runs-on: ubuntu-latest outputs: - matrix: ${{ steps.gen.outputs.matrix }} - count: ${{ steps.gen.outputs.count }} + matrix_nonwindows: ${{ steps.gen.outputs.matrix_nonwindows }} + matrix_windows: ${{ steps.gen.outputs.matrix_windows }} + count_nonwindows: ${{ steps.gen.outputs.count_nonwindows }} + count_windows: ${{ steps.gen.outputs.count_windows }} steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: @@ -74,54 +105,46 @@ jobs: run: | python3 - <<'PY' import json, os, sys, yaml - cfg = yaml.safe_load(open("conan/packages.yml")) only = os.environ.get("ONLY", "").strip() - rows = [] - for dep in cfg["deps"]: - if dep.get("windows_only"): - continue - if only and dep["name"] != only: - continue - opts = dep.get("options") or {} - # Emit options as a flat list of tokens: ["-o", "foo=bar", ...]. - # The consuming job parses this JSON into a bash array to avoid - # shell-glob expansion on `*` in option patterns. - flags = [] - for k, v in opts.items(): - flags.append("-o") - flags.append(f"{k}={v}") - rows.append({ - "name": dep["name"], - "version": dep["version"], - "cci_folder": dep["cci_folder"], - "options_json": json.dumps(flags), - }) - - if only and not rows: + def build_rows(include_windows_only: bool): + rows = [] + for dep in cfg["deps"]: + if dep.get("windows_only") and not include_windows_only: + continue + if only and dep["name"] != only: + continue + rows.append({ + "name": dep["name"], + "version": dep["version"], + "channel": dep["channel"], + "cci_folder": dep["cci_folder"], + }) + return rows + rows_nonwin = build_rows(include_windows_only=False) + rows_win = build_rows(include_windows_only=True) + if only and not (rows_nonwin or rows_win): print(f"::error::--only={only} matched no entry in conan/packages.yml", file=sys.stderr) sys.exit(1) - - payload = json.dumps(rows) - print(f"Matrix rows ({len(rows)}):") - for r in rows: - print(f" {r['name']}/{r['version']} ({r['cci_folder']})") - + print(f"matrix_nonwindows rows ({len(rows_nonwin)}):") + for r in rows_nonwin: + print(f" {r['name']}/{r['version']}@openrv/{r['channel']} ({r['cci_folder']})") + print(f"matrix_windows rows ({len(rows_win)}):") + for r in rows_win: + print(f" {r['name']}/{r['version']}@openrv/{r['channel']} ({r['cci_folder']})") with open(os.environ["GITHUB_OUTPUT"], "a") as f: - f.write(f"matrix={payload}\n") - f.write(f"count={len(rows)}\n") + f.write(f"matrix_nonwindows={json.dumps(rows_nonwin)}\n") + f.write(f"matrix_windows={json.dumps(rows_win)}\n") + f.write(f"count_nonwindows={len(rows_nonwin)}\n") + f.write(f"count_windows={len(rows_win)}\n") PY - # --------------------------------------------------------------------------- - # One matrix row per package. Rocky 8 container, same bootstrap pattern as - # conan-upload-test.yml (base packages, gcc-toolset-11, Kitware CMake, - # Conan 2.x, remote add, login). Each row exports the CCI recipe under - # @openrv/vfx2024, builds, uploads, and asserts server-side listing. + # Rocky Linux 8 - gcc-toolset-11, Python 3.11 from AppStream. # --------------------------------------------------------------------------- - build-upload: - name: "Conan deps: ${{ matrix.name }}/${{ matrix.version }} -> ${{ inputs.remote || 'aswftesting' }}" + rocky8: + name: "rocky8: ${{ matrix.name }}/${{ matrix.version }} -> ${{ inputs.remote || 'aswftesting' }}" needs: prepare-matrix - if: needs.prepare-matrix.outputs.count != '0' + if: needs.prepare-matrix.outputs.count_nonwindows != '0' && contains(format(',{0},', inputs.platforms || 'rocky8,macos,windows'), ',rocky8,') runs-on: ubuntu-latest container: image: amd64/rockylinux:8 @@ -130,11 +153,14 @@ jobs: fail-fast: false max-parallel: 8 matrix: - include: ${{ fromJSON(needs.prepare-matrix.outputs.matrix) }} + include: ${{ fromJSON(needs.prepare-matrix.outputs.matrix_nonwindows) }} env: CONAN_LOGIN_USERNAME: ${{ secrets.ARTIFACTORY_USER }} CONAN_PASSWORD: ${{ secrets.ARTIFACTORY_TOKEN }} + CONAN_PROFILE: x86_64_rocky8 + IS_WINDOWS_JOB: "0" + CCI_DIR: /tmp/cci steps: - name: Verify secrets are set @@ -143,15 +169,11 @@ jobs: echo "::error::ARTIFACTORY_USER or ARTIFACTORY_TOKEN secret is not set on this repo." exit 1 fi - - name: Install base system packages - # VFX Reference Platform CY2024 mandates Python 3.11. Rocky 8's - # default `python3` is 3.6.8, which is too old for meson (>=3.7 - # required), so dav1d/libjpeg-turbo/etc. fail when Conan builds - # meson from source under the default interpreter. Install - # python3.11 from AppStream and expose it as the default - # `python3` / `pip3` via /usr/local/bin so every subsequent step - # (Conan install, recipe build() calls, meson) runs on 3.11. + # VFX Reference Platform CY2025 mandates Python 3.11. Rocky 8's + # default python3 is 3.6.8, too old for meson (>=3.7). Install + # python3.11 from AppStream and expose it as the default `python3` + # via /usr/local/bin so every subsequent step picks it up. run: | dnf install -y epel-release dnf config-manager --set-enabled powertools devel @@ -161,14 +183,12 @@ jobs: ln -sf /usr/bin/pip3.11 /usr/local/bin/pip3 python3 --version dnf clean all - - name: Install gcc-toolset-11 run: | for i in 1 2 3 4 5; do dnf install -y gcc-toolset-11-toolchain && break echo "attempt $i failed, retrying in 5s"; sleep 5 done - - name: Enable gcc-toolset-11 run: | source /opt/rh/gcc-toolset-11/enable @@ -176,13 +196,10 @@ jobs: echo "CC=/opt/rh/gcc-toolset-11/root/usr/bin/gcc" >> $GITHUB_ENV echo "CXX=/opt/rh/gcc-toolset-11/root/usr/bin/g++" >> $GITHUB_ENV gcc --version - - name: Install CMake - # Install under /opt so the subsequent actions/checkout step does not - # wipe it (checkout cleans the workspace by default). Then symlink - # into /usr/local/bin so Conan's self.run(..., env="conanbuild"), - # which can isolate PATH via the generated buildenv.sh, still finds - # cmake when recipe build() methods invoke it. + # Install under /opt so the subsequent actions/checkout step does + # not wipe it, then symlink into /usr/local/bin so Conan's + # buildenv-isolated PATH can still find cmake. run: | curl -SL -o /tmp/cmake.tar.gz "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}-Linux-x86_64.tar.gz" mkdir -p /opt @@ -192,13 +209,11 @@ jobs: ln -sf "/opt/cmake-${CMAKE_VERSION}-linux-x86_64/bin/cpack" /usr/local/bin/cpack echo "/opt/cmake-${CMAKE_VERSION}-linux-x86_64/bin" >> $GITHUB_PATH cmake --version - - - name: Install Conan 2.x + - name: Install Conan 2.x + PyYAML run: | python3 -m pip install --upgrade pip - python3 -m pip install "conan>=2.0,<3.0" + python3 -m pip install "conan>=2.0,<3.0" pyyaml conan --version - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: submodules: false @@ -212,71 +227,264 @@ jobs: conan remote add "$REMOTE_NAME" "$REMOTE_URL" --index 0 conan remote list conan remote login "$REMOTE_NAME" "$CONAN_LOGIN_USERNAME" -p "$CONAN_PASSWORD" - - name: Detect default Conan profile run: conan profile detect --force - name: Clone conan-center-index - run: git clone --depth 1 --branch master https://github.com/conan-io/conan-center-index.git /tmp/cci + run: git clone --depth 1 --branch master https://github.com/conan-io/conan-center-index.git "$CCI_DIR" + + - name: Export every packages.yml recipe + run: python3 ./conan/scripts/export_recipes.py + + - name: Build ${{ matrix.name }}/${{ matrix.version }}@openrv/${{ matrix.channel }} + run: | + # Windows-only: pick up the MSVC bin dir that the earlier + # "Add MSVC cl.exe to msys2 PATH" step appended to bash_profile. + # Harmless no-op on Linux/macOS where the file does not exist. + [ -f ~/.bash_profile ] && source ~/.bash_profile || true + python3 ./conan/scripts/conan_install_target.py \ + "${{ matrix.name }}" "${{ matrix.version }}" "${CONAN_PROFILE}" + conan list "${{ matrix.name }}/${{ matrix.version }}@openrv/${{ matrix.channel }}:*" + - name: Upload all @openrv/* refs built in this cell + run: | + conan upload "*@openrv/common" --remote "$REMOTE_NAME" --confirm + conan upload "*@openrv/vfx2025" --remote "$REMOTE_NAME" --confirm + + - name: Verify server-side listing of target + run: conan search "${{ matrix.name }}/${{ matrix.version }}@openrv/${{ matrix.channel }}" -r "$REMOTE_NAME" + + # --------------------------------------------------------------------------- + # macOS arm64 - macos-14 native runner, Apple clang, Python 3.11 via setup-python. + # --------------------------------------------------------------------------- + macos: + name: "macos-arm64: ${{ matrix.name }}/${{ matrix.version }} -> ${{ inputs.remote || 'aswftesting' }}" + needs: prepare-matrix + if: needs.prepare-matrix.outputs.count_nonwindows != '0' && contains(format(',{0},', inputs.platforms || 'rocky8,macos,windows'), ',macos,') + runs-on: macos-14 - - name: Verify CCI recipe folder exists + strategy: + fail-fast: false + max-parallel: 4 + matrix: + include: ${{ fromJSON(needs.prepare-matrix.outputs.matrix_nonwindows) }} + + env: + CONAN_LOGIN_USERNAME: ${{ secrets.ARTIFACTORY_USER }} + CONAN_PASSWORD: ${{ secrets.ARTIFACTORY_TOKEN }} + CONAN_PROFILE: arm64_apple_release + IS_WINDOWS_JOB: "0" + CCI_DIR: /tmp/cci + # Matches conan.yml's pattern: actions/setup-python + `pip install + # --user` on macOS puts the conan CLI in ~/Library/Python/3.11/bin, + # which is NOT on PATH by default. Hardcode the full path so every + # step (and the helper scripts via $CONAN_EXEC) calls the right + # binary without relying on GITHUB_PATH ordering. + CONAN_EXEC: /Users/runner/Library/Python/3.11/bin/conan + + steps: + - name: Verify secrets are set run: | - DIR="/tmp/cci/recipes/${{ matrix.name }}/${{ matrix.cci_folder }}" - if [ ! -d "$DIR" ]; then - echo "::error::Recipe folder $DIR not found. Siblings:" - ls -1 "/tmp/cci/recipes/${{ matrix.name }}/" || true + if [ -z "$CONAN_LOGIN_USERNAME" ] || [ -z "$CONAN_PASSWORD" ]; then + echo "::error::ARTIFACTORY_USER or ARTIFACTORY_TOKEN secret is not set." exit 1 fi - echo "Using recipe: $DIR" + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + submodules: false + + - name: Install CMake + uses: jwlawson/actions-setup-cmake@802fa1a2c4e212495c05bf94dba2704a92a472be # v2 + with: + cmake-version: "${{ env.CMAKE_VERSION }}" - - name: Verify pinned version is available in CCI + - name: Setup Python + # Runs BEFORE `brew install` so setup-python's PATH prepend wins + # the resolution race. `brew install meson` pulls python@3.x as a + # dep; if brew runs first its python can end up winning `python3` + # for later steps, breaking the `import yaml` the helper scripts + # rely on. + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + with: + python-version: "3.11" + + - name: Install Conan 2.x + PyYAML + # --user lands the CLI in $CONAN_EXEC (see job env). The import + # sanity check fails the step early if the Python that will run + # the helper scripts cannot see the packages we just installed. + run: | + python3 -m pip install --user --upgrade pip + python3 -m pip install --user "conan>=2.0,<3.0" pyyaml + python3 -c "import yaml, conan; print(f'yaml {yaml.__version__}, conan {conan.__version__}')" + "$CONAN_EXEC" --version + - name: Install Homebrew build tools + # nasm, meson: needed as fallbacks for recipes that do not + # tool_require them on macos. autoconf/automake/libtool: GNU + # autotools recipes need these. pkg-config: shared across recipes. + run: brew install nasm meson autoconf automake libtool pkg-config + + - name: Configure Conan remote and authenticate run: | - CONFIG="/tmp/cci/recipes/${{ matrix.name }}/config.yml" - echo "::group::${{ matrix.name }} config.yml" - cat "$CONFIG" - echo "::endgroup::" - if ! grep -q "\"${{ matrix.version }}\"" "$CONFIG"; then - echo "::error::${{ matrix.name }}/${{ matrix.version }} not listed in $CONFIG. Version may have been rotated out of CCI; update conan/packages.yml." + "$CONAN_EXEC" remote remove "$REMOTE_NAME" 2>/dev/null || true + "$CONAN_EXEC" remote add "$REMOTE_NAME" "$REMOTE_URL" --index 0 + "$CONAN_EXEC" remote list + "$CONAN_EXEC" remote login "$REMOTE_NAME" "$CONAN_LOGIN_USERNAME" -p "$CONAN_PASSWORD" + - name: Detect default Conan profile + run: | + "$CONAN_EXEC" profile detect --force + - name: Clone conan-center-index + run: git clone --depth 1 --branch master https://github.com/conan-io/conan-center-index.git "$CCI_DIR" + + - name: Export every packages.yml recipe + run: python3 ./conan/scripts/export_recipes.py + + - name: Build ${{ matrix.name }}/${{ matrix.version }}@openrv/${{ matrix.channel }} + run: | + python3 ./conan/scripts/conan_install_target.py \ + "${{ matrix.name }}" "${{ matrix.version }}" "${CONAN_PROFILE}" + "$CONAN_EXEC" list "${{ matrix.name }}/${{ matrix.version }}@openrv/${{ matrix.channel }}:*" + - name: Upload all @openrv/* refs built in this cell + run: | + "$CONAN_EXEC" upload "*@openrv/common" --remote "$REMOTE_NAME" --confirm + "$CONAN_EXEC" upload "*@openrv/vfx2025" --remote "$REMOTE_NAME" --confirm + - name: Verify server-side listing of target + run: | + "$CONAN_EXEC" search "${{ matrix.name }}/${{ matrix.version }}@openrv/${{ matrix.channel }}" -r "$REMOTE_NAME" + # --------------------------------------------------------------------------- + # Windows x86_64 - windows-2022, MSVC 2022, MSYS2 shell. + # Includes the windows_only entry (pcre2). + # --------------------------------------------------------------------------- + windows: + name: "windows-x86_64: ${{ matrix.name }}/${{ matrix.version }} -> ${{ inputs.remote || 'aswftesting' }}" + needs: prepare-matrix + if: needs.prepare-matrix.outputs.count_windows != '0' && contains(format(',{0},', inputs.platforms || 'rocky8,macos,windows'), ',windows,') + runs-on: windows-2022 + + strategy: + fail-fast: false + max-parallel: 4 + matrix: + include: ${{ fromJSON(needs.prepare-matrix.outputs.matrix_windows) }} + + env: + CONAN_LOGIN_USERNAME: ${{ secrets.ARTIFACTORY_USER }} + CONAN_PASSWORD: ${{ secrets.ARTIFACTORY_TOKEN }} + CONAN_PROFILE: x86_64_windows + IS_WINDOWS_JOB: "1" + # Use a native Windows path; mingw Python and MSYS2 bash both + # agree on drive-letter paths, but disagree on /tmp. + CCI_DIR: "D:/cci" + # Tell MSYS2 to leave these Windows-style path lists alone. + # Without this, MSYS2 rewrites "C:\Foo;C:\Bar" to "/c/Foo:/c/Bar" + # and MSVC's cl.exe loses track of its headers / libs. + MSYS2_ENV_CONV_EXCL: "INCLUDE;LIB;LIBPATH" + + defaults: + run: + shell: msys2 {0} + + steps: + - name: Verify secrets are set + shell: bash + run: | + if [ -z "$CONAN_LOGIN_USERNAME" ] || [ -z "$CONAN_PASSWORD" ]; then + echo "::error::ARTIFACTORY_USER or ARTIFACTORY_TOKEN secret is not set." exit 1 fi + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + submodules: false - - name: Export recipe with user/channel + - name: Setup MSVC + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + + - name: Setup MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + update: true + cache: false + install: >- + mingw-w64-x86_64-toolchain + mingw-w64-x86_64-cmake + mingw-w64-x86_64-make + mingw-w64-x86_64-meson + mingw-w64-x86_64-python + mingw-w64-x86_64-python-pip + mingw-w64-x86_64-python-yaml + autoconf + automake + libtool + nasm + perl + make + git + - name: Add MSVC + Windows SDK to msys2 PATH + # ilammy/msvc-dev-cmd puts cl.exe AND Windows SDK bins (mt.exe, + # rc.exe, signtool.exe, ...) on the runner's Windows PATH, but + # msys2 bash launches with its own PATH. Translate both roots to + # POSIX paths and persist them via ~/.bash_profile so every + # subsequent `msys2 {0}` step can invoke cl + mt (b2's bootstrap + # and the MSVC linker need both). + run: | + if [ -z "$VCToolsInstallDir" ]; then + echo "::error::VCToolsInstallDir not set; Setup MSVC step did not run." + exit 1 + fi + MSVC_BIN=$(cygpath -u "$VCToolsInstallDir/bin/Hostx64/x64") + echo "export PATH=\"$MSVC_BIN:\$PATH\"" >> ~/.bash_profile + echo "Added MSVC bin to PATH: $MSVC_BIN" + if [ -n "$WindowsSdkVerBinPath" ]; then + # $WindowsSdkVerBinPath ends with a trailing backslash; cygpath + # normalises and we append /x64 for the arch-specific tools. + WINSDK_BIN=$(cygpath -u "$WindowsSdkVerBinPath") + echo "export PATH=\"$WINSDK_BIN/x64:\$PATH\"" >> ~/.bash_profile + echo "Added Windows SDK bin to PATH: $WINSDK_BIN/x64" + else + echo "::error::WindowsSdkVerBinPath not set; mt.exe will be unreachable." + exit 1 + fi + - name: Install Conan 2.x (inside msys2) + run: | + source ~/.bash_profile + python -m pip install --upgrade pip + python -m pip install "conan>=2.0,<3.0" + # Expose `python3` for the helper scripts (MSYS2 only ships + # `python` with the mingw python package). + if ! command -v python3 >/dev/null; then + ln -sf "$(command -v python)" /usr/local/bin/python3 + fi + python3 --version + conan --version + - name: Configure Conan remote and authenticate run: | - conan export "/tmp/cci/recipes/${{ matrix.name }}/${{ matrix.cci_folder }}/" \ - --version "${{ matrix.version }}" \ - --user openrv \ - --channel vfx2024 + conan remote remove "$REMOTE_NAME" 2>/dev/null || true + conan remote add "$REMOTE_NAME" "$REMOTE_URL" --index 0 + conan remote list + conan remote login "$REMOTE_NAME" "$CONAN_LOGIN_USERNAME" -p "$CONAN_PASSWORD" + - name: Detect default Conan profile + run: conan profile detect --force - - name: Build ${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024 - env: - OPTIONS_JSON: ${{ matrix.options_json }} - # sh-compatible: emit each option token NUL-terminated from Python, - # pipe to xargs -0 which appends them to the conan argv. Avoids shell - # glob expansion on `*` in option patterns and handles values that - # contain spaces (e.g., boost's extra_b2_flags). - # - # The extra `--build=/*` patterns force Conan to rebuild - # build-time tool_requires from source on the Rocky 8 runner rather - # than pulling prebuilt CCI binaries. Those prebuilts are compiled - # on newer hosts (glibc >= 2.32) and fail to launch against Rocky 8's - # glibc 2.28 (e.g., boost's b2/4.10.1, dav1d's meson/1.4.0 + - # nasm/2.16.01, libjpeg-turbo's nasm). Rebuilding locally also keeps - # the toolchain homogeneous per VFX Reference Platform CY2024 - # ("same compiler for a given OS"). Extend this list if a new - # tool surfaces a `GLIBC_2.xx not found` error. + - name: Clone conan-center-index + run: git clone --depth 1 --branch master https://github.com/conan-io/conan-center-index.git "$CCI_DIR" + + - name: Export every packages.yml recipe + run: python3 ./conan/scripts/export_recipes.py + + - name: Build ${{ matrix.name }}/${{ matrix.version }}@openrv/${{ matrix.channel }} + run: | + # Windows-only: pick up the MSVC bin dir that the earlier + # "Add MSVC cl.exe to msys2 PATH" step appended to bash_profile. + # Harmless no-op on Linux/macOS where the file does not exist. + [ -f ~/.bash_profile ] && source ~/.bash_profile || true + python3 ./conan/scripts/conan_install_target.py \ + "${{ matrix.name }}" "${{ matrix.version }}" "${CONAN_PROFILE}" + conan list "${{ matrix.name }}/${{ matrix.version }}@openrv/${{ matrix.channel }}:*" + - name: Upload all @openrv/* refs built in this cell run: | - python3 -c "import json,sys; sys.stdout.write(''.join(t + '\0' for t in json.loads(sys.argv[1])))" "$OPTIONS_JSON" \ - | xargs -0 conan install \ - --requires="${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024" \ - --build=missing \ - --build="b2/*" \ - --build="meson/*" \ - --build="nasm/*" \ - -pr:a "./conan/profiles/${CONAN_PROFILE}" - conan list "${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024:*" - - - name: Upload ${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024 - run: conan upload "${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024" --remote "$REMOTE_NAME" --confirm - - - name: Verify server-side listing - run: conan search "${{ matrix.name }}/${{ matrix.version }}@openrv/vfx2024" -r "$REMOTE_NAME" + conan upload "*@openrv/common" --remote "$REMOTE_NAME" --confirm + conan upload "*@openrv/vfx2025" --remote "$REMOTE_NAME" --confirm + + - name: Verify server-side listing of target + run: conan search "${{ matrix.name }}/${{ matrix.version }}@openrv/${{ matrix.channel }}" -r "$REMOTE_NAME" \ No newline at end of file diff --git a/conan/packages.yml b/conan/packages.yml index 82eab6eb6..cbfdb9535 100644 --- a/conan/packages.yml +++ b/conan/packages.yml @@ -1,13 +1,18 @@ -# OpenRV Conan dependencies published under @openrv/vfx2024. +# OpenRV Conan dependencies published to the ASWF Conan remote. # # Single source of truth consumed by .github/workflows/conan-upload-deps.yml. # Each entry mirrors openrvcore-conanfile.py:63-128 (name, version, options # on conan create). The workflow builds each on x86_64_rocky8 and uploads # to the ASWF Conan remote (aswftesting by default). # +# Year-specific deps (from CY2025.cmake) use channel "vfx2025"; +# year-independent deps (from CYCOMMON.cmake) use channel "common". +# # Fields: # name - Conan package name (matches CCI recipe folder). # version - Pinned version; must be listed in CCI config.yml. +# channel - Conan channel: "vfx2025" for year-specific deps, +# "common" for year-independent deps. # cci_folder - Subfolder under recipes// in conan-center-index. # Most are "all"; a few like openssl use "3.x.x". # options - Map of Conan option -> value. Passed as -o flags on @@ -19,12 +24,14 @@ deps: - name: zlib version: "1.3.2" + channel: common cci_folder: all options: "zlib/*:shared": "True" - name: libatomic_ops version: "7.10.0" + channel: common cci_folder: all options: "libatomic_ops/*:shared": "False" @@ -34,12 +41,14 @@ deps: # sharpyuv and causes issues with OIIO. CCI rotated 1.2.1 out; 1.2.4 # is the closest available that remains pre-1.3.0. version: "1.2.4" + channel: common cci_folder: all options: "libwebp/*:shared": "False" - name: dav1d version: "1.5.3" + channel: common cci_folder: all options: "dav1d/*:shared": "True" @@ -48,6 +57,7 @@ deps: # 2.1.4 rotated out of CCI; 2.1.5 is the closest 2.1.x available. # Avoiding 3.x to prevent ABI surprises against libraw/openjph. version: "2.1.5" + channel: common cci_folder: all options: "libjpeg-turbo/*:shared": "True" @@ -56,8 +66,9 @@ deps: # The recipe revision pin #7053477b271b8c39e046f784405b402f from # openrvcore-conanfile.py:87 may be unresolvable on CCI master. # Workflow strips any #rrev suffix before conan create; the produced - # @openrv/vfx2024 ref gets its own revision. + # @openrv/vfx2025 ref gets its own revision. version: "1.82.0" + channel: vfx2025 cci_folder: all options: "boost/*:shared": "True" @@ -65,18 +76,21 @@ deps: - name: imath version: "3.1.12" + channel: vfx2025 cci_folder: all options: "imath/*:shared": "True" - name: libdeflate version: "1.25" + channel: common cci_folder: all options: "libdeflate/*:shared": "True" - name: openexr version: "3.3.6" + channel: vfx2025 cci_folder: "3.x" options: "openexr/*:shared": "True" @@ -84,12 +98,14 @@ deps: - name: libpng # 1.6.55 rotated; 1.6.58 is a patch bump within 1.6.x. version: "1.6.58" + channel: common cci_folder: all options: "libpng/*:shared": "True" - name: openjpeg version: "2.5.4" + channel: common cci_folder: all options: "openjpeg/*:shared": "True" @@ -98,6 +114,7 @@ deps: # 0.21.1 rotated; 0.21.2 is a patch bump within 0.21.x. # 0.21.5b has a beta suffix, avoided. version: "0.21.2" + channel: common cci_folder: all options: "libraw/*:shared": "True" @@ -108,6 +125,7 @@ deps: # 0.26.3 rotated; 0.27.0 is the only remaining version in CCI. # Minor bump; validate CMake target name compatibility. version: "0.27.0" + channel: common cci_folder: all options: "openjph/*:shared": "True" @@ -115,6 +133,7 @@ deps: - name: pcre2 version: "10.44" + channel: common cci_folder: all windows_only: true options: diff --git a/conan/profiles/common b/conan/profiles/common index a8d3ee511..76d652d73 100644 --- a/conan/profiles/common +++ b/conan/profiles/common @@ -1,8 +1,10 @@ # Common settings shared across all OpenRV profiles. # -# Redirect every OpenRV-managed dependency to the prebuilt binary published -# under @openrv/vfx2024 on the ASWF Conan remote (aswf-conan-dev for testing, -# aswf-conan for production). Consumers must have one of those remotes +# Redirect every OpenRV-managed dependency to prebuilt binaries published +# on the ASWF Conan remote (aswf-conan-dev for testing, aswf-conan for +# production). Year-specific deps (CY2025.cmake) use @openrv/vfx2025; +# year-independent deps (CYCOMMON.cmake) use @openrv/common. Consumers +# must have one of those remotes # configured before running `conan install`. The versions below track # conan/packages.yml, which is the single source of truth for what the # conan-upload-deps.yml workflow builds and uploads. @@ -14,19 +16,19 @@ # covered here. [replace_requires] -zlib/*: zlib/1.3.1@openrv/vfx2024 -libatomic_ops/*: libatomic_ops/7.10.0@openrv/vfx2024 -libwebp/*: libwebp/1.2.4@openrv/vfx2024 -dav1d/*: dav1d/1.5.3@openrv/vfx2024 -libjpeg/*: libjpeg-turbo/2.1.5@openrv/vfx2024 -libjpeg-turbo/*: libjpeg-turbo/2.1.5@openrv/vfx2024 -boost/*: boost/1.82.0@openrv/vfx2024 -imath/*: imath/3.2.2@openrv/vfx2024 -libdeflate/*: libdeflate/1.25@openrv/vfx2024 -openexr/*: openexr/3.2.8@openrv/vfx2024 -libpng/*: libpng/1.6.58@openrv/vfx2024 -openjpeg/*: openjpeg/2.5.4@openrv/vfx2024 -libraw/*: libraw/0.21.2@openrv/vfx2024 -openjph/*: openjph/0.27.0@openrv/vfx2024 -pcre2/*: pcre2/10.44@openrv/vfx2024 -openssl/*: openssl/3.5.6@openrv/vfx2024 +zlib/*: zlib/1.3.1@openrv/common +libatomic_ops/*: libatomic_ops/7.10.0@openrv/common +libwebp/*: libwebp/1.2.4@openrv/common +dav1d/*: dav1d/1.5.3@openrv/common +libjpeg/*: libjpeg-turbo/2.1.5@openrv/common +libjpeg-turbo/*: libjpeg-turbo/2.1.5@openrv/common +boost/*: boost/1.82.0@openrv/vfx2025 +imath/*: imath/3.2.2@openrv/vfx2025 +libdeflate/*: libdeflate/1.25@openrv/common +openexr/*: openexr/3.2.8@openrv/vfx2025 +libpng/*: libpng/1.6.58@openrv/common +openjpeg/*: openjpeg/2.5.4@openrv/common +libraw/*: libraw/0.21.2@openrv/common +openjph/*: openjph/0.27.0@openrv/common +pcre2/*: pcre2/10.44@openrv/common +openssl/*: openssl/3.5.6@openrv/vfx2025 From 9717cb1e908f3bdcee6d935b4a75d5aea2573742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Tue, 5 May 2026 13:33:58 -0400 Subject: [PATCH 14/20] Add CI job to validate conan profiles against packages.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduced a new job in the conan-upload-deps workflow to ensure that the section in is in sync with . - Added a Python script to facilitate the validation and regeneration of the profile section. - Updated the job to depend on the new validation job. - Made minor updates to dependency versions in and for consistency. Signed-off-by: Cédrik Fuoco --- .github/workflows/conan-upload-deps.yml | 27 ++++++- .github/workflows/conan-upload-test.yml | 10 --- conan/packages.yml | 20 +++-- conan/profiles/common | 8 +- conan/scripts/conan_install_target.py | 81 +++++++++++++++++++ conan/scripts/export_recipes.py | 71 +++++++++++++++++ conan/scripts/gen_profile_common.py | 101 ++++++++++++++++++++++++ openrvcore-conanfile.py | 89 ++++++--------------- 8 files changed, 320 insertions(+), 87 deletions(-) create mode 100644 conan/scripts/conan_install_target.py create mode 100644 conan/scripts/export_recipes.py create mode 100755 conan/scripts/gen_profile_common.py diff --git a/.github/workflows/conan-upload-deps.yml b/.github/workflows/conan-upload-deps.yml index e144d648d..3627d909a 100644 --- a/.github/workflows/conan-upload-deps.yml +++ b/.github/workflows/conan-upload-deps.yml @@ -39,9 +39,6 @@ on: push: branches: - main - # Temporary: auto-run on the Conan-ASWF test branch while manual - # workflow dispatch is not available. Remove once testing is done. - - find-fork-test-aswf pull_request: @@ -72,6 +69,29 @@ env: PLATFORMS: ${{ inputs.platforms || 'rocky8,macos,windows' }} jobs: + # --------------------------------------------------------------------------- + # Validates that conan/profiles/common [replace_requires] is in sync with + # conan/packages.yml. Fails fast before any build jobs run. + # To fix: run `python3 conan/scripts/gen_profile_common.py` and commit. + # --------------------------------------------------------------------------- + check-profile-sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0 + with: + python-version: "3.11" + + - name: Install PyYAML + run: python3 -m pip install --user pyyaml + + - name: Validate profiles/common matches packages.yml + run: python3 conan/scripts/gen_profile_common.py --check + # --------------------------------------------------------------------------- # Reads conan/packages.yml and emits two matrices: # matrix_nonwindows - excludes windows_only entries (Linux + macOS jobs) @@ -79,6 +99,7 @@ jobs: # Optionally narrows to a single package via the `only` input. # --------------------------------------------------------------------------- prepare-matrix: + needs: check-profile-sync runs-on: ubuntu-latest outputs: matrix_nonwindows: ${{ steps.gen.outputs.matrix_nonwindows }} diff --git a/.github/workflows/conan-upload-test.yml b/.github/workflows/conan-upload-test.yml index b3982e2c8..1f800908f 100644 --- a/.github/workflows/conan-upload-test.yml +++ b/.github/workflows/conan-upload-test.yml @@ -15,16 +15,6 @@ name: Conan Upload Test (ASWF Artifactory) # namespace policy is confirmed. on: - push: - branches: - # This will run when PR is merged or direct pushes to main. - - main - # Temporary: auto-run on the Conan-ASWF test branch while manual - # workflow dispatch is not available. Remove once testing is done. - - find-fork-test-aswf - - pull_request: # This handles PR creation and subsequent commits. - workflow_dispatch: inputs: phase: diff --git a/conan/packages.yml b/conan/packages.yml index cbfdb9535..27a31112e 100644 --- a/conan/packages.yml +++ b/conan/packages.yml @@ -1,9 +1,9 @@ -# OpenRV Conan dependencies published to the ASWF Conan remote. +# OpenRV Conan dependencies - single source of truth for the Conan build path. # -# Single source of truth consumed by .github/workflows/conan-upload-deps.yml. -# Each entry mirrors openrvcore-conanfile.py:63-128 (name, version, options -# on conan create). The workflow builds each on x86_64_rocky8 and uploads -# to the ASWF Conan remote (aswftesting by default). +# Consumed by: +# - .github/workflows/conan-upload-deps.yml (CI upload) +# - openrvcore-conanfile.py requirements() (reads versions + options at runtime) +# - conan/scripts/gen_profile_common.py (generates profiles/common replace_requires) # # Year-specific deps (from CY2025.cmake) use channel "vfx2025"; # year-independent deps (from CYCOMMON.cmake) use channel "common". @@ -131,6 +131,16 @@ deps: "openjph/*:shared": "True" "openjph/*:with_tiff": "False" + - name: openssl + # Used to override the openssl version pulled in transitively by ffmpeg. + # Not used directly by OpenRV at runtime. + version: "3.6.2" + channel: vfx2025 + cci_folder: "3.x.x" + options: + "openssl/*:shared": "True" + "openssl/*:no_zlib": "True" + - name: pcre2 version: "10.44" channel: common diff --git a/conan/profiles/common b/conan/profiles/common index 76d652d73..d91a60d6e 100644 --- a/conan/profiles/common +++ b/conan/profiles/common @@ -16,19 +16,19 @@ # covered here. [replace_requires] -zlib/*: zlib/1.3.1@openrv/common +zlib/*: zlib/1.3.2@openrv/common libatomic_ops/*: libatomic_ops/7.10.0@openrv/common libwebp/*: libwebp/1.2.4@openrv/common dav1d/*: dav1d/1.5.3@openrv/common libjpeg/*: libjpeg-turbo/2.1.5@openrv/common libjpeg-turbo/*: libjpeg-turbo/2.1.5@openrv/common boost/*: boost/1.82.0@openrv/vfx2025 -imath/*: imath/3.2.2@openrv/vfx2025 +imath/*: imath/3.1.12@openrv/vfx2025 libdeflate/*: libdeflate/1.25@openrv/common -openexr/*: openexr/3.2.8@openrv/vfx2025 +openexr/*: openexr/3.3.6@openrv/vfx2025 libpng/*: libpng/1.6.58@openrv/common openjpeg/*: openjpeg/2.5.4@openrv/common libraw/*: libraw/0.21.2@openrv/common openjph/*: openjph/0.27.0@openrv/common +openssl/*: openssl/3.6.2@openrv/vfx2025 pcre2/*: pcre2/10.44@openrv/common -openssl/*: openssl/3.5.6@openrv/vfx2025 diff --git a/conan/scripts/conan_install_target.py b/conan/scripts/conan_install_target.py new file mode 100644 index 000000000..0f85f2d5e --- /dev/null +++ b/conan/scripts/conan_install_target.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +"""Build a single target package from conan/packages.yml using conan install. + +Usage: + python3 conan/scripts/conan_install_target.py + +Reads packages.yml to look up the dep's channel and options, then runs: + conan install --requires=/@openrv/ + --build=missing --build=b2/* --build=meson/* --build=nasm/* + -pr:a ./conan/profiles/ + -o