t4 #388
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build pypylon | |
| # Controls when the action will run. | |
| on: | |
| # Triggers the workflow on push or pull request events but only for the master branch | |
| push: | |
| branches: | |
| - '**' | |
| tags: | |
| - '*.*.*' | |
| pull_request: | |
| branches: [ master ] | |
| # Allows you to run this workflow manually from the Actions tab | |
| workflow_dispatch: | |
| env: | |
| TWINE_USERNAME: __token__ | |
| # Uncomment the relevant lines to switch between deployment to test.pypi.org or pypi.org | |
| TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} | |
| # TWINE_REPOSITORY_URL: https://test.pypi.org/legacy/ | |
| # TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }} | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| is_release_build: ${{ env.RELEASE_BUILD == '1' }} | |
| steps: | |
| - uses: jfrog/setup-jfrog-cli@v4 | |
| env: | |
| JF_URL: ${{ secrets.SDK_URL }} | |
| JF_ACCESS_TOKEN: ${{ secrets.SDK_TOKEN }} | |
| with: | |
| disable-auto-build-publish: true | |
| disable-job-summary: true | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check for release build and tag | |
| if: startsWith(github.ref, 'refs/tags/') | |
| run: | | |
| TAG_NAME="${GITHUB_REF#refs/tags/}" | |
| echo "Build release for $TAG_NAME" | |
| echo "RELEASE_BUILD=1" >> $GITHUB_ENV | |
| echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV | |
| # login | |
| - name: Authenticate to Artifactory | |
| run: | | |
| jf c add --url=$JF_URL --access-token=$JF_ACCESS_TOKEN --interactive=false | |
| # download | |
| - name: Download control files from Artifactory | |
| id: get_sdks | |
| run: | | |
| set +x | |
| set -e | |
| build_config=$(cat .github/workflows/build_config.json) | |
| # Get the latest pylon version from Artifactory | |
| pylon_default_version=$(jf rt s "pylon-artifacts-generic-prod/setup/*" | jq '.[] | .path' | awk -F'/' '{print $3}' | sort -V | uniq | tac | head -n 1) | |
| for os in $(echo $build_config | jq -r 'keys[]'); do | |
| # When TAG_NAME is set (release build), use the pylon version from the tag | |
| tag="${TAG_NAME:-$pylon_default_version}" | |
| echo "Downloading control files for $os using pylon $tag" | |
| # Download control files | |
| for path in $(jf rt s "pylon-artifacts-generic-prod/setup/*/report_$os*.json" | jq -r --arg tag "$tag" '.[] | select(.path | test($tag)) | .path'); do | |
| jf rt dl --flat $path ./${os,,}/report_${os,,}.json | |
| done | |
| # Download 3rd party licenses | |
| for path in $(jf rt s "pylon-artifacts-generic-prod/setup/*/oso_$os*.txt" | jq -r --arg tag "$tag" '.[] | select(.path | test($tag)) | .path'); do | |
| jf rt dl --flat $path ./${os,,}/pylon_Third-Party_Licenses.txt | |
| done | |
| done | |
| - name: Upload control files for Linux aarch64 | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Linux_aarch64_Pylon | |
| path: linux_aarch64 | |
| - name: Upload control files for Linux x86_64 | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Linux_x86_64_Pylon | |
| path: linux_x86_64 | |
| - name: Upload control files for Windows | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: Windows_Pylon | |
| path: windows | |
| - name: Upload control files for macOS | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: macOS_Pylon | |
| path: macos | |
| download: | |
| needs: prepare | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ ubuntu-24.04, ubuntu-24.04-arm, macos-14, windows-latest ] | |
| arch: [ x64, arm64 ] | |
| exclude: | |
| # Exclude ARM64 architecture for windows-latest | |
| - os: windows-latest | |
| arch: arm64 | |
| # Exclude X64 architecture for macos-14 | |
| - os: macos-14 | |
| arch: x64 | |
| # Exclude ARM64 architecture for ubuntu-24.04 | |
| - os: ubuntu-24.04 | |
| arch: arm64 | |
| # Exclude X64 architecture for ubuntu-24.04-arm | |
| - os: ubuntu-24.04-arm | |
| arch: x64 | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.10" | |
| - name: Detect running os | |
| id: osname | |
| run: | | |
| import re | |
| import os | |
| os_str = "${{ matrix.os }}" | |
| os_name_arch = "${{ matrix.arch }}" | |
| os_name = re.sub(r'-.*', '', os_str) | |
| os_name = os_name.replace('ubuntu', 'linux') | |
| if os_name == 'linux' and os_name_arch == 'arm64': | |
| os_name_arch = 'linux_aarch64' | |
| elif os_name == 'linux' and os_name_arch == 'x64': | |
| os_name_arch = 'linux_x86_64' | |
| elif os_name == 'macos': | |
| os_name_arch = 'macos' | |
| elif os_name == 'windows': | |
| os_name_arch = 'windows' | |
| os_name_camel = os_name.replace('linux', 'Linux').replace('windows', 'Windows').replace('macos', 'macOS') | |
| os_name_arch_camel = os_name_arch.replace('linux', 'Linux').replace('windows', 'Windows').replace('macos', 'macOS') | |
| with open(os.environ['GITHUB_OUTPUT'], 'a') as f: | |
| f.write(f"value={os_name}\n") | |
| f.write(f"value_camel={os_name_camel}\n") | |
| f.write(f"value_arch={os_name_arch}\n") | |
| f.write(f"value_arch_camel={os_name_arch_camel}\n") | |
| shell: python | |
| - name: Install conan v1 | |
| run: pip install "conan<2" | |
| - name: Add conan v1 remote and authenticate | |
| env: | |
| JF_URL: ${{ secrets.SDK_URL }} | |
| JF_USER: ${{ secrets.SDK_USER }} | |
| JF_ACCESS_TOKEN: ${{ secrets.SDK_TOKEN }} | |
| run: | | |
| import os | |
| import subprocess | |
| subprocess.run(["conan", "config", "set", "general.revisions_enabled=1"], check=True) | |
| subprocess.run([ | |
| "conan", "remote", "add", "pylon-conan-prod", | |
| f"{os.environ['JF_URL']}/artifactory/api/conan/pylon-conan-prod", "--insert", "0" | |
| ], check=True) | |
| subprocess.run([ | |
| "conan", "user", "-p", os.environ["JF_ACCESS_TOKEN"], | |
| "-r", "pylon-conan-prod", os.environ["JF_USER"] | |
| ], check=True) | |
| shell: python | |
| - name: Download ${{ steps.osname.outputs.value_arch_camel }} control artifacts | |
| uses: actions/download-artifact@v5 | |
| with: | |
| pattern: ${{ steps.osname.outputs.value_camel }}*Pylon | |
| merge-multiple: true | |
| path: pylon-install-files | |
| - name: Download need pylon modules | |
| run: | | |
| import os | |
| import subprocess | |
| subprocess.run([ | |
| "conan", "install", "--update", "--install-folder", "conan", | |
| "-pr", os.path.join(os.environ['GITHUB_WORKSPACE'], ".github", "workflows", "profiles", "${{ steps.osname.outputs.value }}_${{ matrix.arch }}"), | |
| "-o", f"pypylon:build_config={os.path.join(os.environ['GITHUB_WORKSPACE'], '.github', 'workflows', 'build_config.json')}", | |
| "-o", f"pypylon:control_file={os.path.join(os.environ['GITHUB_WORKSPACE'], 'pylon-install-files', 'report_${{ steps.osname.outputs.value_arch }}.json')}", | |
| "-o", f"pypylon:third_party_license_file={os.path.join(os.environ['GITHUB_WORKSPACE'], 'pylon-install-files', 'pylon_Third-Party_Licenses.txt')}", | |
| "-c", "tools.system.package_manager:mode=install", | |
| "-c", "tools.system.package_manager:sudo=True", | |
| os.path.join(os.environ['GITHUB_WORKSPACE'], ".github", "workflows", "conanfile.py") | |
| ], check=True) | |
| shell: python | |
| - name: Tar pylon SDK files | |
| if: runner.os == 'Linux' || runner.os == 'macOS' | |
| run: cd conan && tar -czf ../pylon_sdk.tar.gz . | |
| - name: Upload pylon SDK for ${{ steps.osname.outputs.value_arch_camel }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ steps.osname.outputs.value_arch_camel }}_Pylon_SDK | |
| path: ${{ runner.os == 'Windows' && 'conan' || 'pylon_sdk.tar.gz' }} | |
| build-linux: | |
| needs: download | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ ubuntu-24.04, ubuntu-24.04-arm ] | |
| a: [3.9] | |
| p: [manylinux_2_31_x86_64, manylinux_2_31_aarch64] | |
| exclude: | |
| # Exclude manylinux_2_31_aarch64 on ubuntu-24.04 | |
| - os: ubuntu-24.04 | |
| p: manylinux_2_31_aarch64 | |
| # Exclude manylinux_2_31_x86_64 on ubuntu-24.04-arm | |
| - os: ubuntu-24.04-arm | |
| p: manylinux_2_31_x86_64 | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| P: ${{ matrix.p }} | |
| A: ${{ matrix.a }} | |
| # Steps represent a sequence of tasks that will be executed as part of the job | |
| steps: | |
| # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.10" | |
| - name: Detect docker parameters | |
| id: dockerparams | |
| run: | | |
| import re | |
| import os | |
| # Extract python version and remove dot for pyver_tag | |
| pyver_tag = "${{ matrix.a }}" | |
| pyver_tag_nodot = pyver_tag.replace('.', '') | |
| # Extract ubuntu version and architecture from the os string | |
| os_str = "${{ matrix.os }}" | |
| match = re.match(r'(ubuntu-\d+\.\d+)(?:-(arm))?', os_str) | |
| if match: | |
| base_os = match.group(1) | |
| arch_from_os = match.group(2) | |
| if arch_from_os == "arm": | |
| artifacts_name = "Linux_aarch64_Pylon_SDK" | |
| docker_base_arch = "arm64v8" | |
| docker_platform = "linux/arm64" | |
| qemu_target_arch = "aarch64" | |
| else: | |
| artifacts_name = "Linux_x86_64_Pylon_SDK" | |
| docker_base_arch = "amd64" | |
| docker_platform = "linux/amd64" | |
| qemu_target_arch = "x86_64" | |
| else: | |
| raise ValueError(f"Unexpected OS format: {os_str}") | |
| with open(os.environ['GITHUB_OUTPUT'], 'a') as f: | |
| f.write(f"docker_base_arch={docker_base_arch}\n") | |
| f.write(f"docker_platform={docker_platform}\n") | |
| f.write(f"qemu_target_arch={qemu_target_arch}\n") | |
| f.write(f"artifacts_name={artifacts_name}\n") | |
| f.write(f"pyver_tag=cp{pyver_tag_nodot}\n") | |
| shell: python | |
| # download the pylon sdks | |
| - name: download linux artifacts | |
| uses: actions/download-artifact@v5 | |
| with: | |
| pattern: ${{ steps.dockerparams.outputs.artifacts_name }} | |
| path: pylon-sdk | |
| - name: Unpack pylon SDK to pylon-sdk folder | |
| run: | | |
| tar -xzf pylon-sdk/pylon_sdk.tar.gz -C pylon-sdk | |
| - name: Display Structure of downloaded files | |
| run: ls pylon-sdk | |
| - name: Build docker container for pypylon build | |
| run: | | |
| docker build --platform "${{ steps.dockerparams.outputs.docker_platform }}" \ | |
| --build-arg "QEMU_TARGET_ARCH=${{ steps.dockerparams.outputs.qemu_target_arch }}" \ | |
| --build-arg "DOCKER_BASE_IMAGE=${{ steps.dockerparams.outputs.docker_base_arch }}/python:${{ matrix.a }}-bullseye" \ | |
| --build-arg "CMD_WRAPPER=linux64" \ | |
| --tag "pypylon-${{ matrix.p }}-${{ steps.dockerparams.outputs.pyver_tag }}-${{ github.run_id }}" - < ${{ github.workspace }}/scripts/build/Dockerfile.debian | |
| - name: Build pypylon wheel | |
| run: | | |
| docker run -v "${{ github.workspace }}:/work" \ | |
| -v "${{ github.workspace }}/.github/workflows/scripts:/work/scripts/cibuild" \ | |
| -v "${{ github.workspace }}/pylon-sdk/pylon:/opt/pylon" -e PYLON_ROOT="/opt/pylon" \ | |
| --user $(id -u) pypylon-${{ matrix.p }}-${{ steps.dockerparams.outputs.pyver_tag }}-${{ github.run_id }} /work/scripts/cibuild/build.sh --update-platform-tag ${{ matrix.p }} | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-results-${{ matrix.p }}-${{ steps.dockerparams.outputs.pyver_tag }} | |
| path: dist/* | |
| - name: Upload Release Asset | |
| if: needs.setup.outputs.is_release_build == 'true' | |
| uses: softprops/action-gh-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| files: dist/* | |
| - name: Publish package to (Test)PyPI | |
| if: needs.setup.outputs.is_release_build == 'true' && startsWith( matrix.p, 'manylinux' ) | |
| run: | | |
| sudo pip3 install "twine==6.0.1" | |
| python3 -m twine upload --non-interactive --skip-existing dist/* | |
| build-windows: | |
| needs: download | |
| runs-on: windows-latest | |
| strategy: | |
| fail-fast: false | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.9" | |
| - name: Download pylon SDK | |
| uses: actions/download-artifact@v5 | |
| with: | |
| pattern: Windows_Pylon_SDK | |
| path: pylon-sdk | |
| - name: Display Structure of downloaded files | |
| run: dir pylon-sdk | |
| - name: Build wheels | |
| uses: pypa/cibuildwheel@v2.21.3 | |
| env: | |
| PYLON_DEV_DIR: ${{ github.workspace }}\pylon-sdk\pylon\Development | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-results-windows | |
| path: ./wheelhouse/*.whl | |
| - name: Upload Release Asset | |
| if: needs.setup.outputs.is_release_build == 'true' | |
| uses: softprops/action-gh-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| files: ./wheelhouse/*.whl | |
| - name: Publish package to (Test)PyPI | |
| if: needs.setup.outputs.is_release_build == 'true' | |
| run: | | |
| python -m pip install twine | |
| python -m twine upload --non-interactive --skip-existing wheelhouse\\* | |
| shell: cmd | |
| build-macos: | |
| needs: download | |
| runs-on: macos-latest | |
| strategy: | |
| fail-fast: false | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.9" | |
| - uses: actions/download-artifact@v5 | |
| with: | |
| name: macOS_Pylon_SDK | |
| path: pylon-sdk | |
| - name: Unpack pylon SDK to pylon-sdk folder | |
| run: | | |
| tar -xzf pylon-sdk/pylon_sdk.tar.gz -C pylon-sdk | |
| - name: Display Structure of downloaded files | |
| run: ls pylon-sdk | |
| - name: Build wheels | |
| uses: pypa/cibuildwheel@v2.21.3 | |
| env: | |
| PYLON_FRAMEWORK_ARM64: ${{ github.workspace }}/pylon-sdk/pylon/Frameworks | |
| PYLON_FRAMEWORK_X86_64: ${{ github.workspace }}/pylon-sdk/pylon/Frameworks | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-results-macos | |
| path: ./wheelhouse/*.whl | |
| - name: Upload Release Asset | |
| if: needs.setup.outputs.is_release_build == 'true' | |
| uses: softprops/action-gh-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| files: ./wheelhouse/*.whl | |
| - name: Publish package to (Test)PyPI | |
| if: needs.setup.outputs.is_release_build == 'true' | |
| run: | | |
| sudo pip3 install twine | |
| python3 -m twine upload --non-interactive --skip-existing wheelhouse/* | |
| cleanup: | |
| if: always() | |
| needs: [ | |
| prepare, | |
| download, | |
| build-linux, | |
| build-macos, | |
| build-windows | |
| ] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: geekyeggo/delete-artifact@v5 | |
| continue-on-error: true | |
| with: | |
| name: | | |
| Linux_x86_64_Pylon | |
| Linux_x86_64_Pylon_SDK | |
| Linux_aarch64_Pylon | |
| Linux_aarch64_Pylon_SDK | |
| Windows_Pylon | |
| Windows_Pylon_SDK | |
| macOS_Pylon | |
| macOS_Pylon_SDK | |
| unit-tests: | |
| if: success() | |
| needs: cleanup | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ ubuntu-24.04, ubuntu-24.04-arm, macos-14, windows-latest ] | |
| python-version: [ '3.9', '3.10', '3.11', '3.12', '3.13' ] | |
| architecture: [ x64, arm64 ] | |
| exclude: | |
| # Exclude ARM64 architecture for windows-latest | |
| - os: windows-latest | |
| architecture: arm64 | |
| # Exclude ARM64 architecture for ubuntu-24.04 | |
| - os: ubuntu-24.04 | |
| architecture: arm64 | |
| # Exclude X64 architecture for ubuntu-24.04-arm | |
| - os: ubuntu-24.04-arm | |
| architecture: x64 | |
| # Exclude python 3.9 - 3.10 on macOS x86_64 due too issues with the runner image | |
| # See also GitHub issue: https://github.com/actions/setup-python/issues/825 | |
| - os: macos-14 | |
| architecture: x64 | |
| python-version: 3.9 | |
| - os: macos-14 | |
| architecture: x64 | |
| python-version: 3.10 | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v2 | |
| - uses: dkershner6/switch-case-action@v1 | |
| id: pypylon-wheel-source | |
| with: | |
| default: "build-results-unknown" | |
| conditionals-with-values: | | |
| ${{ runner.os == 'Linux' && matrix.architecture == 'arm64' }} => build-results-manylinux_2_31_aarch64-cp39 | |
| ${{ runner.os == 'Linux' && matrix.architecture == 'x64' }} => build-results-manylinux_2_31_x86_64-cp39 | |
| ${{ runner.os == 'Windows' }} => build-results-windows | |
| ${{ runner.os == 'macOS' }} => build-results-macos | |
| - name: Download pypylon wheels | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: ${{ steps.pypylon-wheel-source.outputs.value }} | |
| path: pypylon-wheels | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| architecture: ${{ matrix.architecture }} | |
| - name: Set up needed linux requirements | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update && sudo apt-get install -y locales | |
| sudo sed -i 's/^# *\(fr_FR.UTF-8\)/\1/' /etc/locale.gen | |
| sudo locale-gen | |
| - name: Run pypylon unit tests for Python ${{ matrix.python-version }} | |
| if: runner.os != 'macOS' | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install pytest numpy | |
| pip install --no-index --find-links pypylon-wheels pypylon | |
| pytest tests/genicam_tests tests/pylon_tests/emulated tests/pylondataprocessing_tests | |
| - uses: dkershner6/switch-case-action@v1 | |
| if: runner.os == 'macOS' | |
| id: pypylon-macos-arch | |
| with: | |
| default: "unknown" | |
| conditionals-with-values: | | |
| ${{ matrix.architecture == 'arm64' }} => arm64 | |
| ${{ matrix.architecture == 'x64' }} => x86_64 | |
| - name: Run pypylon unit tests for Python ${{ matrix.python-version }} without pylon Data Processing | |
| if: runner.os == 'macOS' | |
| run: | | |
| arch -${{ steps.pypylon-macos-arch.outputs.value }} python -m pip install --upgrade pip | |
| arch -${{ steps.pypylon-macos-arch.outputs.value }} pip install pytest numpy | |
| arch -${{ steps.pypylon-macos-arch.outputs.value }} pip install --no-index --find-links pypylon-wheels pypylon | |
| arch -${{ steps.pypylon-macos-arch.outputs.value }} pytest tests/genicam_tests tests/pylon_tests/emulated |