NEURON Release #102
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: NEURON Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| rel_branch: | |
| description: 'Release branch/commit' | |
| default: 'release/x.y' | |
| required: true | |
| rel_tag: | |
| description: 'Release version (tag name)' | |
| default: 'x.y.z' | |
| required: true | |
| python_versions: | |
| description: "Comma-separated list of supported Python versions" | |
| default: "3.9,3.10,3.11,3.12,3.13" | |
| required: true | |
| type: string | |
| os: | |
| description: "Comma-separated list of OSes (for wheels only)" | |
| default: "macos-13,macos-14,ubuntu-22.04,ubuntu-22.04-arm" | |
| required: true | |
| type: string | |
| upload: | |
| description: "Whether to actually upload any files (releases, wheels, etc.)" | |
| required: true | |
| default: false | |
| type: boolean | |
| env: | |
| GH_REPO: ${{ github.server_url }}/${{ github.repository }} | |
| REL_TAG: ${{ github.event.inputs.rel_tag }} | |
| REL_BRANCH: ${{ github.event.inputs.rel_branch }} | |
| jobs: | |
| get-latest-wheel-version: | |
| name: Get the latest wheel version from PyPI | |
| runs-on: ubuntu-latest | |
| outputs: | |
| latest_version: ${{ steps.latest-wheel-version.outputs.latest_version }} | |
| steps: | |
| - name: Get the latest wheel version from PyPI | |
| id: latest-wheel-version | |
| run: | | |
| # taken from: | |
| # https://safjan.com/how-to-check-latest-version-of-python-package/ | |
| echo "latest_version=$(curl -s https://pypi.org/pypi/neuron/json | jq -r '.info.version')" >> "$GITHUB_OUTPUT" | |
| generate-wheel-matrix: | |
| name: Generate platform and Python matrix for wheels | |
| # wheels should be built once the full source package builds successfully | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.set-matrix.outputs.matrix }} | |
| steps: | |
| - id: set-matrix | |
| run: | | |
| OS_INPUT="${{ github.event.inputs.os || 'macos-13,macos-14,ubuntu-22.04,ubuntu-22.04-arm' }}" | |
| PY_INPUT="${{ github.event.inputs.python_versions || '3.9,3.10,3.11,3.12,3.13' }}" | |
| OS_JSON=$(echo "$OS_INPUT" | jq -R 'split(",")') | |
| PY_JSON=$(echo "$PY_INPUT" | jq -R 'split(",")') | |
| echo "matrix=$(jq -c -n --argjson os "$OS_JSON" --argjson py "$PY_JSON" '{os: $os, python_version: $py}')" >> "$GITHUB_OUTPUT" | |
| # we need to build wheels _before_ running modelDB CI, since it only works | |
| # with wheels, and not the CMake installer | |
| build-wheels: | |
| name: Build and test wheel on ${{ matrix.os }} with Python ${{ matrix.python_version }} | |
| needs: | |
| - generate-wheel-matrix | |
| - tag-n-release | |
| uses: ./.github/workflows/wheels-template.yml | |
| strategy: | |
| matrix: ${{ fromJson(needs.generate-wheel-matrix.outputs.matrix) }} | |
| with: | |
| platform: ${{ matrix.os }} | |
| python_version: ${{ matrix.python_version }} | |
| optimize_rxd: true | |
| commit: ${{ needs.tag-n-release.outputs.ref }} # Uses tag (if upload=true) or branch | |
| version: ${{ github.event.inputs.rel_tag }} | |
| build_type: 'release' | |
| merge-wheels: | |
| name: Merge wheel files to one artifact | |
| runs-on: ubuntu-latest | |
| needs: | |
| - build-wheels | |
| outputs: | |
| artifacts-url: ${{ steps.merge-artifacts.outputs.artifacts-url }} | |
| steps: | |
| - name: Merge Artifacts | |
| id: merge-artifacts | |
| uses: actions/upload-artifact/merge@v4 | |
| with: | |
| delete-merged: true | |
| name: wheels | |
| pattern: wheels-* | |
| nrn-modeldb-ci: | |
| name: Run modelDB CI relative to ${{ needs.get-latest-wheel-version.outputs.latest_version }} | |
| needs: | |
| - get-latest-wheel-version | |
| - merge-wheels | |
| uses: neuronsimulator/nrn-modeldb-ci/.github/workflows/nrn-modeldb-ci.yaml@master | |
| with: | |
| # v1 is the latest stable wheel, while v2 is the currently-built wheel. | |
| # Note that v2 needs to at least contain an x86_64 Linux Python 3.9 wheel since that is the platform that modelDB CI uses | |
| neuron_v1: neuron==${{ needs.get-latest-wheel-version.outputs.latest_version }} | |
| neuron_v2: ${{ needs.merge-wheels.outputs.artifacts-url }} | |
| nrn-full-src-package: | |
| name: Create the full-src package | |
| runs-on: ubuntu-latest | |
| outputs: | |
| topdir: ${{ steps.create-full-src.outputs.topdir }} | |
| filename: ${{ steps.create-full-src.outputs.filename }} | |
| steps: | |
| - name: Checkout feature-rich code | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 1 | |
| ref: ${{ github.event.inputs.rel_branch }} | |
| - name: Create nrn-full-src-package artifact | |
| id: create-full-src | |
| run: | | |
| filename="nrn-full-src-package-${{ env.REL_TAG }}.tar.gz" | |
| echo "filename=$filename" >> "$GITHUB_OUTPUT" | |
| topdir="nrn-${{ env.REL_TAG }}" | |
| echo "topdir=${topdir}" >> "$GITHUB_OUTPUT" | |
| # taken from: | |
| # https://stackoverflow.com/a/67389978 | |
| git ls-files --recurse-submodules > nrn_files | |
| # we also need the .git dir for now | |
| find .git >> nrn_files | |
| # cannot use --xform as it screws up the symbolic links. So | |
| # do a normal tar, untar into topdir, and tar again. | |
| mkdir -p tmp/$topdir | |
| tar -c -T nrn_files | tar -x -C tmp/$topdir | |
| (cd tmp && tar caf ../$filename $topdir) | |
| rm -rf tmp | |
| - name: Upload nrn-full-src-package artifact | |
| uses: actions/upload-artifact@v4 | |
| id: upload-full-src | |
| with: | |
| name: nrn-full-src-package | |
| path: ${{ steps.create-full-src.outputs.filename }} | |
| test-full-src-package: | |
| name: Build and test the full-src package | |
| runs-on: ubuntu-latest | |
| needs: | |
| - nrn-full-src-package | |
| steps: | |
| - name: Install apt packages | |
| run: | | |
| sudo apt-get install -y bison flex libreadline-dev libfl-dev libmpich-dev | |
| - name: Setup cmake | |
| uses: jwlawson/actions-setup-cmake@v2 | |
| with: | |
| cmake-version : '3.18' | |
| - name: Set up Python | |
| id: setup-python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| - name: Download nrn-full-src-package artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: nrn-full-src-package | |
| - name: Build nrn-full-src-package | |
| run: | | |
| tar xf ${filename} | |
| python -m venv ${venv_dir} | |
| source ${venv_dir}/bin/activate | |
| if [[ -f "${topdir}/ci/requirements.txt" ]]; then | |
| python -m pip install -r ${topdir}/ci/uv_requirements.txt | |
| uv pip install -r ${topdir}/ci/requirements.txt | |
| else | |
| python -m pip install -r ${topdir}/nrn_requirements.txt | |
| fi | |
| # we build a simple configuration to save on CI time | |
| cmake -B build -DNRN_ENABLE_INTERVIEWS=OFF -DNRN_ENABLE_MPI=OFF -DNMODL_ENABLE_PYTHON_BINDINGS=OFF -DNRN_ENABLE_CORENEURON=OFF -S ${topdir}/ | |
| cmake --build build --parallel $(nproc) | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| topdir: ${{ needs.nrn-full-src-package.outputs.topdir }} | |
| filename: ${{ needs.nrn-full-src-package.outputs.filename }} | |
| venv_dir: venv_${{ steps.setup-python.outputs.python-version }} | |
| nrn-build-ci: | |
| name: Run build CI | |
| needs: | |
| - merge-wheels | |
| uses: neuronsimulator/nrn-build-ci/.github/workflows/build-neuron-template.yml@main | |
| with: | |
| artifact_url: ${{ needs.merge-wheels.outputs.artifacts-url }} | |
| neuron_branch: ${{ github.event.inputs.rel_branch }} | |
| repo: 'neuronsimulator/nrn-build-ci' | |
| pypi-publish: | |
| name: Upload wheels to PyPI | |
| if: github.event.inputs.upload == 'true' | |
| needs: | |
| - merge-wheels | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/neuron | |
| permissions: | |
| id-token: write # IMPORTANT: this permission is mandatory for trusted publishing | |
| steps: | |
| - name: Download wheels from artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: wheels | |
| path: dist/ | |
| - name: Publish package distributions to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| # actually creates a git tag and a release on GitHub | |
| tag-n-release: | |
| runs-on: ubuntu-latest | |
| name: tag-n-release ${{ github.event.inputs.rel_tag }} (${{ github.event.inputs.rel_branch }}) | |
| outputs: | |
| release_url: ${{ steps.create_release.outputs.upload_url }} | |
| rel_tag: ${{ env.REL_TAG }} | |
| ref: ${{ steps.build-ref.outputs.ref }} # Conditional ref for builds | |
| steps: | |
| - uses: actions/checkout@v4 | |
| name: Checkout branch ${{ env.REL_BRANCH }} | |
| with: | |
| ref: ${{ github.event.inputs.rel_branch }} | |
| - name: Determine build ref # Sets ref to tag (if upload=true) or branch | |
| id: build-ref | |
| run: | | |
| if [[ "${{ github.event.inputs.upload }}" == 'true' ]]; then | |
| echo "ref=${{ env.REL_TAG }}" >> $GITHUB_OUTPUT | |
| else | |
| echo "ref=${{ github.event.inputs.rel_branch }}" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Create and upload tag ${{ env.REL_TAG }} | |
| # Moved the earlier `if` to here so the build items can succeed with upload false | |
| if: github.event.inputs.upload == 'true' | |
| run: | | |
| git config user.name github-actions | |
| git config user.email github-actions@github.com | |
| git tag -a $REL_TAG -m "${REL_TAG}" | |
| git push origin $REL_TAG | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| working-directory: ${{runner.workspace}}/nrn | |
| - name: Create Release | |
| if: github.event.inputs.upload == 'true' # Skip on dry runs | |
| id: create_release | |
| uses: ncipollo/release-action@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag: ${{ github.event.inputs.rel_tag }} | |
| name: Release ${{ github.event.inputs.rel_tag }} | |
| prerelease: true | |
| upload-src-package: | |
| name: Publish full-src package | |
| runs-on: ubuntu-latest | |
| if: github.event.inputs.upload == 'true' | |
| needs: | |
| - nrn-full-src-package | |
| - tag-n-release | |
| steps: | |
| - name: Download nrn-full-src-package artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: nrn-full-src-package | |
| - name: Upload to GitHub release | |
| run: | | |
| gh release upload ${{ env.REL_TAG }} ${{ needs.nrn-full-src-package.outputs.filename }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| build-windows-installer: | |
| name: Build Windows installer | |
| needs: | |
| - tag-n-release | |
| uses: neuronsimulator/nrn/.github/workflows/windows.yml@master | |
| with: | |
| tag: ${{ needs.tag-n-release.outputs.ref }} | |
| upload-windows-installer: | |
| name: Publish Windows installer | |
| if: github.event.inputs.upload == 'true' | |
| needs: | |
| - build-windows-installer | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download Windows installer artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: nrn-nightly-AMD64.exe | |
| - name: Rename Windows installer | |
| id: rename | |
| run: | | |
| # convert "3.9,3.10..." into "39-310-..." | |
| py_version_string="$(echo "${{ github.event.inputs.python_versions }}" | sed 's/\.//g; s/,/-/g')" | |
| win_installer_name="nrn-${{ env.REL_TAG }}.w64-mingw-py-${py_version_string}-setup.exe" | |
| echo "win_installer_name=${win_installer_name}" >> "$GITHUB_OUTPUT" | |
| cp nrn-nightly-AMD64.exe "${win_installer_name}" | |
| ls -lha "${win_installer_name}" | |
| - name: Publish Windows installer | |
| run: | | |
| gh release upload ${{ env.REL_TAG }} ${{ steps.rename.outputs.win_installer_name }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |