!yamlscript/v0


defn pywhl(pyv cibwpyv cibwarch cibwplatform os vsenvarch='' cmkflags='')::  # NOTE: cannot use _ in names?
    name:: "python/$pyv/$cibwplatform"
    sfx:: "python$pyv-$cibwplatform" # suffix
    os:: os
    pythonv:: pyv
    cibw_pyv:: cibwpyv #pyv.replace(/\.//) # WTF??
    cibw_arch:: cibwarch
    cibw_platform:: cibwplatform
    #cmakeflags:: cmkflags
    vsenvarch:: vsenvarch


python-wheel-matrix =::
#          pyv        arch     platform           os
- ! pywhl('3.13' 313 'x86_64' 'manylinux_x86_64' 'ubuntu-24.04')
- ! pywhl('3.13' 313 'i686'   'manylinux_i686'   'ubuntu-24.04')
- ! pywhl('3.13' 313 'x86_64' 'macosx_x86_64'    'macos-13'    )
#
- ! pywhl('3.12' 312 'x86_64' 'manylinux_x86_64' 'ubuntu-24.04')
- ! pywhl('3.12' 312 'i686'   'manylinux_i686'   'ubuntu-24.04')
- ! pywhl('3.12' 312 'x86_64' 'macosx_x86_64'    'macos-13'    )
#
- ! pywhl('3.11' 311 'x86_64' 'manylinux_x86_64' 'ubuntu-24.04')
- ! pywhl('3.11' 311 'i686'   'manylinux_i686'   'ubuntu-24.04')
- ! pywhl('3.11' 311 'x86_64' 'macosx_x86_64'    'macos-13'    )
#
- ! pywhl('3.10' 310 'x86_64' 'manylinux_x86_64' 'ubuntu-24.04')
- ! pywhl('3.10' 310 'i686'   'manylinux_i686'   'ubuntu-24.04')
- ! pywhl('3.10' 310 'x86_64' 'macosx_x86_64'    'macos-13'    )
#
- ! pywhl('3.9'  39 'x86_64'  'manylinux_x86_64' 'ubuntu-24.04')
- ! pywhl('3.9'  39 'i686'    'manylinux_i686'   'ubuntu-24.04')
- ! pywhl('3.9'  39 'x86_64'  'macosx_x86_64'    'macos-13'    )
#
- ! pywhl('3.8'  38 'x86_64'  'manylinux_x86_64' 'ubuntu-24.04')
- ! pywhl('3.8'  38 'i686'    'manylinux_i686'   'ubuntu-24.04')
- ! pywhl('3.8'  38 'x86_64'  'macosx_x86_64'    'macos-13'    )
#
- ! pywhl('3.7'  37 'x86_64'  'manylinux_x86_64' 'ubuntu-22.04')
- ! pywhl('3.7'  37 'i686'    'manylinux_i686'   'ubuntu-22.04')
- ! pywhl('3.7'  37 'x86_64'  'macosx_x86_64'    'macos-13'    )
#
- ! pywhl('3.6'  36 'x86_64'  'manylinux_x86_64' 'ubuntu-20.04') # setup-python 3.6 requires ubuntu 20.04
- ! pywhl('3.6'  36 'i686'    'manylinux_i686'   'ubuntu-20.04') # setup-python 3.6 requires ubuntu 20.04
- ! pywhl('3.6'  36 'x86_64'  'macosx_x86_64'    'macos-13'    )


python-wheel-matrix-win =::
#          pyv        arch     platform     os       vsenvarch   cmakeflags
- ! pywhl('3.13' 313 'AMD64'  'win_amd64'  'windows-2022' 'x64' '-G "Visual Studio 17 2022" -A x64')
- ! pywhl('3.13' 313 'x86'    'win32'      'windows-2022' 'x86' '-G "Visual Studio 17 2022" -A Win32')
#
- ! pywhl('3.12' 312 'AMD64'  'win_amd64'  'windows-2022' 'x64' '-G "Visual Studio 17 2022" -A x64')
- ! pywhl('3.12' 312 'x86'    'win32'      'windows-2022' 'x86' '-G "Visual Studio 17 2022" -A Win32')
#
- ! pywhl('3.11' 311 'AMD64'  'win_amd64'  'windows-2022' 'x64' '-G "Visual Studio 17 2022" -A x64')
- ! pywhl('3.11' 311 'x86'    'win32'      'windows-2022' 'x86' '-G "Visual Studio 17 2022" -A Win32')
#
- ! pywhl('3.10' 310 'AMD64'  'win_amd64'  'windows-2022' 'x64' '-G "Visual Studio 17 2022" -A x64')
- ! pywhl('3.10' 310 'x86'    'win32'      'windows-2022' 'x86' '-G "Visual Studio 17 2022" -A Win32')
#
- ! pywhl('3.9'  39  'AMD64'  'win_amd64'  'windows-2022' 'x64' '-G "Visual Studio 17 2022" -A x64')
- ! pywhl('3.9'  39  'x86'    'win32'      'windows-2022' 'x86' '-G "Visual Studio 17 2022" -A Win32')
#
- ! pywhl('3.8'  38  'AMD64'  'win_amd64'  'windows-2022' 'x64' '-G "Visual Studio 17 2022" -A x64')
- ! pywhl('3.8'  38  'x86'    'win32'      'windows-2022' 'x86' '-G "Visual Studio 17 2022" -A Win32')
#
- ! pywhl('3.7'  37  'AMD64'  'win_amd64'  'windows-2022' 'x64' '-G "Visual Studio 17 2022" -A x64')
#- ! pywhl('3.7'  37  'x86'    'win32'      'windows-2022' 'x86' '-G "Visual Studio 17 2022" -A Win32')
#
- ! pywhl('3.6'  36  'AMD64'  'win_amd64'  'windows-2022' 'x64' '-G "Visual Studio 17 2022" -A x64')
- ! pywhl('3.6'  36  'x86'    'win32'      'windows-2022' 'x86' '-G "Visual Studio 17 2022" -A Win32')


setup-env =::
- name: setup env (non-win)
  run: echo 'nothing to do'


setup-env-win =::
- name: setup env (Visual Studio)
  uses: TheMrMilchmann/setup-msvc-dev@v3
  with:
    arch: ${{matrix.config.vsenvarch}}


---
!yamlscript/v0:

:use common: :all
:workflow-setup 'release'::
  push:
    tags: [v0.*, v1.*, v2.*]
    branches: [master]
::
  defn define-workflow-python-wheels(name matrix setup-env)::
      :: setup-job('release' name)
      name: ${{matrix.config.name}}
      runs-on: ${{matrix.config.os}}
      env:
        CMAKE_FLAGS: ${{matrix.config.cmakeflags}} -DCMAKE_VERBOSE_MAKEFILES=ON -DRYML_DEV=OFF -DRYML_API_TESTS=OFF -DRYML_API_BENCHMARKS=OFF
        CIBW_BUILD: cp${{matrix.config.cibw_pyv}}-${{matrix.config.cibw_platform}}
        CIBW_ARCHS: ${{matrix.config.cibw_arch}}
        CIBW_BUILD_VERBOSITY: 2
      strategy:
        fail-fast: false
        matrix:
          config:: matrix
      steps:
      - :: checkout-action
      - :: setup-env
      - name: create wheel
        uses: pypa/cibuildwheel@v2.23
      - name: rename wheelhouse -> dist
        run: mv -fv wheelhouse dist
      - name: Verify artifacts
        run: ls -lFhp dist/
      - name: Save artifacts for publishing to PyPI
        uses: actions/upload-artifact@v4
        with: {name: 'dist-${{matrix.config.sfx}}', path: dist/}
      # run the tests
      - name: install python ${{matrix.config.pythonv}}
        uses: actions/setup-python@v5
        with:
          python-version: ${{matrix.config.pythonv}}
      - name: test with python ${{matrix.config.pythonv}}
        run: |
          set -x
          echo "python ${{matrix.config.pythonv}} ${{matrix.config.py_arch}} ${{matrix.config.cibw_arch}}"
          # skip 32 bit tests, as Python 32 bits are not available in ubuntu
          arch="${{matrix.config.cibw_arch}}"
          if [ "$arch" == "x86" ] || [ "$arch" == "i686" ] ; then
            exit 0
          fi
          python --version
          python -c 'import sys ; import struct ; print("python:", sys.version, struct.calcsize("P") * 8, "bits")'
          pip --version
          pip install -v -r requirements.txt
          pip install -v -r api/python/requirements.txt
          for whl in dist/* ; do
            # verify that we can import the wheel files without installing the wheel
            unzip -l $whl
            mkdir -p tmpwhl
            cd tmpwhl
            unzip ../$whl
            ls -lFpAR .
            ( export PYTHONPATH=`pwd`/ryml ; python -c 'import ryml' )
            cd ..
            rm -rf tmpwhl
            # verify that we can install the wheel and then import it
            pip install -v $whl
            pip show -f rapidyaml
            python -c 'import ryml'
            python -c 'import ryml ; print("ryml", ryml.version, ryml.version_tuple)'
            python -c 'import ryml ; tree = ryml.parse_in_arena(b"{foo: bar}") ; assert tree.key(1) == b"foo" ; assert tree.val(1) == b"bar" ; print(str(tree.key(1), "utf8")) ; print(str(tree.val(1), "utf8"))'
            python -m pytest -vvv api/python/tests
            pip uninstall -y -v rapidyaml
          done

  =>: nil # this is needed to expose the function above

env:
  PROJ_PKG_NAME: rapidyaml-
  PROJ_PFX_TARGET: ryml-
  PROJ_PFX_CMAKE: RYML_
  CMAKE_FLAGS: -DRYML_TEST_SUITE=OFF
  NUM_JOBS_BUILD: # 4

# useful to iterate when fixing the release:
# ver=0.2.1
# (set -xe; git tag -d v$ver; git push origin :v$ver)
# (set -xe
#  tbump --only-patch --non-interactive $ver
#  git add -u; git commit --amend --no-edit
#  git tag --annotate --message "v$ver" "v$ver"
#  git push -f --tags origin )

jobs:

  gettag:
    :: setup-job('release' 'gettag')
    runs-on: ubuntu-latest
    steps:
    - :: checkout-action
    - :: version-discover

  #----------------------------------------------------------------------------
  # create source packages
  src:
    :: setup-job('release' 'src')
    needs: gettag
    runs-on: ubuntu-latest
    steps:
    - :: checkout-action
    - :: version-get-vars
    - name: Install python 3.9
      uses: actions/setup-python@v5
      with: { python-version: 3.9 }
    - name: Install requirements
      run: sudo -E pip install git-archive-all
    - name: Create source packages
      run: |
        pwd
        ls -lFhp
        source vars.sh
        echo SRC_TAG=$SRC_TAG
        echo SRC_VERSION=$SRC_VERSION
        id=${PROJ_PKG_NAME}${SRC_VERSION}
        name=${id}-src
        mkdir -p assets
        git-archive-all --prefix $name assets/$name.tgz
        git-archive-all --prefix $name assets/$name.zip
        python --version
        python tools/amalgamate.py assets/$id.hpp
    - name: Save source artifacts
      uses: actions/upload-artifact@v4
      with: {name: assets-src, path: assets/}

  #----------------------------------------------------------------------------
  # create c++ packages
  cpp:
    :: setup-job('release' 'cpp')
    name: cpp/${{matrix.config.os}}/${{matrix.config.gen}}
    needs: gettag
    runs-on: ${{matrix.config.os}}
    env:
      DEV:  OFF
      BT:   Release
      OS:   ${{matrix.config.os}}
      CXX_: ${{matrix.config.cxx}}
      GEN:  ${{matrix.config.gen}}
    strategy:
      fail-fast: false
      matrix:
        config:
        #  name of the artifact | suffix (gen) | suffix (package) |
        #  cpack gen | mime type | os | cxx
        - {name: Ubuntu 24.04 deb,
           sfxg: unix64.deb,
           sfxp: ubuntu-24.04.deb,
           gen: DEB, mime: vnd.debian.binary-package, os: ubuntu-24.04}
        - {name: Ubuntu 22.04 deb,
           sfxg: unix64.deb,
           sfxp: ubuntu-22.04.deb,
           gen: DEB, mime: vnd.debian.binary-package, os: ubuntu-22.04}
       #- {name: Ubuntu 18.04 deb,
       #   sfxg: unix64.deb,
       #   sfxp: ubuntu-18.04.deb,
       #   gen: DEB, mime: vnd.debian.binary-package, os: ubuntu-18.04}
        - {name: Windows VS2019 zip,
           sfxg: win64.zip,
           sfxp: windows-vs2019.zip,
           gen: ZIP, mime: zip, os: windows-2019, cxx: vs2019}
        - {name: MacOSX sh,
           sfxg: apple64.sh,
           sfxp: macosx-xcode.sh,
           gen: STGZ, mime: x-sh, os: macos-latest, cxx: xcode}
    steps:
    - :: checkout-action
    - :: version-get-vars
    - name: install requirements
      run: source .github/reqs.sh && c4_install_test_requirements $OS
    - name: show info
      run: source .github/setenv.sh && c4_show_info
    - name: shared64-configure-------------------------------------------------
      run: source .github/setenv.sh && c4_cfg_test shared64
    - name: shared64-build
      run: source .github/setenv.sh && c4_build_target shared64
    - name: shared64-pack
      run: source .github/setenv.sh && c4_package shared64 $GEN
    - name: shared64-normalize
      run:: bash('release-shared-normalize')
    - name: Save artifacts
      uses: actions/upload-artifact@v4
      with: {name: 'assets-${{matrix.config.sfxp}}', path: assets/}

  #----------------------------------------------------------------------------
  # create python packages

  python_src:
    :: setup-job('release' 'python_src')
    name: python/src
    runs-on: ubuntu-latest
    steps:
      - :: checkout-action
      - name: install python 3.9
        uses: actions/setup-python@v5
        with: {python-version: 3.9}
      - name: package python src packages
        run:: bash('release-package-python')
      - name: normalize src package names
        run:: bash('release-normalize')
      - name: Save artifacts
        uses: actions/upload-artifact@v4
        with: {name: dist-python_src, path: dist/}

  python_wheels:
    :: define-workflow-python-wheels('python_wheels' python-wheel-matrix setup-env)

  python_wheels_win:
    :: define-workflow-python-wheels('python_wheels_win' python-wheel-matrix-win setup-env-win)

  #----------------------------------------------------------------------------
  merge_artifacts:
    :: setup-job('release' 'merge_artifacts')
    runs-on: ubuntu-latest
    needs: [src, cpp, python_src, python_wheels, python_wheels_win]
    steps:
      - name: Merge assets artifacts
        uses: actions/upload-artifact/merge@v4
        with:
          name: assets
          pattern: assets-*
          separate-directories: true
          delete-merged: true
      - name: Merge dist artifacts
        uses: actions/upload-artifact/merge@v4
        with:
          name: dist
          pattern: dist-*
          separate-directories: true
          delete-merged: true

  #----------------------------------------------------------------------------
  release:
    :: setup-job('release' 'release')
    runs-on: ubuntu-latest
    needs: [merge_artifacts]
    steps:
    - :: checkout-action
    - :: version-get-vars
    # artifacts
    - name: Verify existing artifacts
      run: |
        ls -lFhp .
        ls -lFhp assets*/ || echo 'none found'
        ls -lFhp dist*/ || echo 'none found'
    - name: Gather artifacts - ./assets
      uses: actions/download-artifact@v4
      with: {pattern: assets}
    - name: Gather artifacts - ./dist
      uses: actions/download-artifact@v4
      with: {pattern: dist}
    - name: Verify existing artifacts
      run: |
        ls -lFhp .
        ls -lFhp assets*/ || echo 'none found'
        ls -lFhp dist*/ || echo 'none found'
        ( \
          cd assets ; \
          for asset in assets-*/ ; do \
            ls -lFhpA $asset/ ; \
            mv -v $asset/* . ; \
            rmdir $asset ; \
          done ;
        )
        ( \
          cd dist ; \
          for dist in dist-*/ ; do \
            ls -lFhpA $dist/ ; \
            mv -v $dist/* . ; \
            rmdir $dist ; \
          done ; \
        )
        ls -lFhp assets*/ || echo 'none found'
        ls -lFhp dist*/ || echo 'none found'
    - name: Move Python packages to assets folder
      if: contains(github.ref, 'tags/v')
      run: mv -fv dist/*src.zip assets/.
    # Github
    - :: version-get-vars
    - name: Create Github Release
      if: contains(github.ref, 'tags/v')
      id: create_release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
      with:
        tag_name: ${{github.ref}}
        release_name: Release ${{env.SRC_VERSION}}
        body_path: ${{env.SRC_VERSION_BODY}}
        draft: true
        prerelease: ${{contains(github.ref, 'rc')}}
    - name: Upload assets to Github Release
      if: contains(github.ref, 'tags/v')
      uses: dwenegar/upload-release-assets@v1
      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
      with:
        release_id: ${{steps.create_release.outputs.id}}
        assets_path: ./assets/
    # PyPI (test)
    - name: Publish python packages to test PyPI
      uses: pypa/gh-action-pypi-publish@v1.4.2
      with:
        repository_url: https://test.pypi.org/legacy/
        user: __token__
        password: ${{secrets.PYPI_TOKEN_TEST}}
        verbose: true
        skip_existing: true
    # PyPI (production)
    - name: Publish python packages to production PyPI
      if: contains(github.ref, 'tags/v')
      uses: pypa/gh-action-pypi-publish@v1.4.2
      with:
        user: __token__
        password: ${{secrets.PYPI_TOKEN}}
        verbose: true
