Skip to content

NEURON Release

NEURON Release #102

Workflow file for this run

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 }}