Skip to content

Add release workflow #699

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions +tests/+unit/+file/CloneNwbTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ function testCloneNwbFile(testCase)

function restoreNwbFileClass(classDefStr)
fid = fopen( fullfile(misc.getMatnwbDir(), 'NwbFile.m'), 'wt' );
if ispc % Ad hoc fix when saving to file using fwrite on pc
classDefStr = strrep(classDefStr, newline, '');
end
fwrite(fid, classDefStr);
fclose(fid);
end
4 changes: 3 additions & 1 deletion +tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
hdf5plugin
scipy
matplotlib
hdf5plugin
dataframe_image
git+https://github.com/NeurodataWithoutBorders/nwbinspector.git@dev
git+https://github.com/NeurodataWithoutBorders/pynwb.git@dev
242 changes: 242 additions & 0 deletions .github/workflows/prepare_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
# Run MATLAB tests across multiple MATLAB versions and create a draft release

name: Prepare release
on:
workflow_dispatch:
inputs:
version:
description: 'Version number in major.minor.patch format, i.e 2.8.0'
required: true
type: string

jobs:
validate_version:
runs-on: ubuntu-latest
steps:
- name: Check version format
run: |
version="${{ github.event.inputs.version }}"
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Input for 'version' ('$version') is not in the expected major.minor.patch format."
exit 1
fi
echo "Version '$version' is valid."

run_tests:
name: Run MATLAB tests (${{ matrix.matlab-version }} on ${{ matrix.os }})
runs-on: ${{ matrix.os }}
needs: [validate_version]
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macos-13]
matlab-version: [R2021a, R2021b, R2022a, R2022b, R2023a, R2023b, R2024a, R2024b]
include:
- matlab-version: R2021a
python-version: '3.9'
skip-pynwb-compatibilty-test-for-tutorial: '1'
- matlab-version: R2021b
python-version: '3.9'
skip-pynwb-compatibilty-test-for-tutorial: '1'
- matlab-version: R2022a
python-version: '3.9'
skip-pynwb-compatibilty-test-for-tutorial: '0'
- matlab-version: R2022b
python-version: '3.9'
skip-pynwb-compatibilty-test-for-tutorial: '0'
- matlab-version: R2023a
python-version: '3.10'
skip-pynwb-compatibilty-test-for-tutorial: '0'
- matlab-version: R2023b
python-version: '3.10'
skip-pynwb-compatibilty-test-for-tutorial: '0'
- matlab-version: R2024a
python-version: '3.11'
skip-pynwb-compatibilty-test-for-tutorial: '0'
- matlab-version: R2024b
python-version: '3.11'
skip-pynwb-compatibilty-test-for-tutorial: '0'
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Install python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install python dependencies
run: |
python -m pip install -U pip
pip install -r +tests/requirements.txt
python -m pip list

- name: Configure python env (macOS, ubuntu)
if: runner.os != 'Windows'
run: |
echo "HDF5_PLUGIN_PATH=$(python -c "import hdf5plugin; print(hdf5plugin.PLUGINS_PATH)")" >> "$GITHUB_ENV"

- name: Configure python env (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$pluginPath = python -c "import hdf5plugin; print(hdf5plugin.PLUGINS_PATH)"
Add-Content -Path $env:GITHUB_ENV -Value "HDF5_PLUGIN_PATH=$pluginPath"

- name: Install MATLAB
uses: matlab-actions/setup-matlab@v2
with:
release: ${{ matrix.matlab-version }}

- name: Run tests
uses: matlab-actions/run-command@v2
env:
HDF5_PLUGIN_PATH: ${{ env.HDF5_PLUGIN_PATH }}
with:
command: |
setenv("SKIP_PYNWB_COMPATIBILITY_TEST_FOR_TUTORIALS", ...
num2str(${{ matrix.skip-pynwb-compatibilty-test-for-tutorial }}))
pyenv("ExecutionMode", "OutOfProcess");
results = assertSuccess(nwbtest('ReportOutputFolder', '.'));
assert(~isempty(results), 'No tests ran');

- name: Upload JUnit results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.os }}-${{ matrix.matlab-version }}
path: testResults.xml

publish_junit:
name: Publish JUnit test results
runs-on: ubuntu-latest
if: always()
needs: [run_tests]
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Retrieve result files
uses: actions/download-artifact@v4
with:
pattern: test-results-*
merge-multiple: false

- name: Publish test results
uses: mikepenz/action-junit-report@v4
with:
report_paths: '*/testResults.xml'

update_version:
name: Create new draft relase for given version
runs-on: ubuntu-latest
needs: [run_tests]
steps:
- name: Checkout repository using deploy key
uses: actions/checkout@v4
with:
ref: refs/heads/main
ssh-key: ${{ secrets.DEPLOY_KEY }}

- name: Update Contents.m file
run: |
# Read the template file
template=$(cat .github/workflows/templates/contents_header_template.txt)

# Get current date in DD-MMM-YYYY format
date_string=$(date +"%d-%b-%Y")

# Get current year
year_number=$(date +"%Y")

# Replace placeholders in template
header="${template/\{\{version_number\}\}/${{ github.event.inputs.version }}}"
header="${header/\{\{date_string\}\}/$date_string}"
header="${header/\{\{year_number\}\}/$year_number}"

# Extract the content after the header from the current Contents.m file
content=$(awk '/^% -{10,}/{flag=1;next} flag{print}' Contents.m)

# Combine new header with existing content
echo "$header" > Contents.m
echo "$content" >> Contents.m

- name: Commit updated Contents.m file
continue-on-error: true
run: |
git config user.name "${{ github.workflow }} by ${{ github.actor }}"
git config user.email "<>"
git add Contents.m
git commit -m "Update version number in Contents.m"
git fetch
git push

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12' # Pinned to 3.12 because of pybadges dependencies

- name: Generate tested with badge
run: |
pip install --upgrade setuptools
pip install pybadges
mkdir -p .github/badges/v${{ inputs.version }}
python -c "
from pybadges import badge
with open('.github/badges/v${{ inputs.version }}/tested_with.svg', 'w') as f:
f.write(badge(
left_text='tested with',
right_text='R2021a | R2021b | R2022a | R2022b | R2023a | R2023b | R2024 | R2024b',
right_color='green'
))
"

- name: Tag repository with version tag
if: always()
run: |
git fetch

git config user.name "${{ github.workflow }} by ${{ github.actor }}"
git config user.email "<>"

# Create the tag with a message
git tag -a "${{ inputs.version }}" -m "Release ${{ inputs.version }}"

# Push the new tag to the remote repository
git push origin "${{ inputs.version }}"

# Commit the SVG for the MATLAB releases test badge to gh-badges branch
- name: Checkout gh-badges branch
uses: actions/checkout@v4
with:
ref: gh-badges
path: gh-badges

- name: Push to gh-badges
run: |
mkdir -p gh-badges/.github/badges/v${{ inputs.version }}
cp .github/badges/v${{ inputs.version }}/tested_with.svg gh-badges/.github/badges/v${{ inputs.version }}/tested_with.svg
cd gh-badges

git config user.name "${{ github.workflow }} by ${{ github.actor }}"
git config user.email "<>"

# Only proceed with commit and push if changes are detected
if [[ $(git add .github/badges/* --dry-run | wc -l) -gt 0 ]]; then
git add .github/badges/*
git commit -m "Update 'tested_with' badge for release v${{ inputs.version }}"
git push -f
else
echo "Nothing to commit"
fi

# Create the release
- name: Create GitHub release
uses: ncipollo/release-action@v1
with:
draft: true
tag: ${{ inputs.version }}
generateReleaseNotes: true
body: |
![Tested On Platforms](https://raw.githubusercontent.com/NeurodataWithoutBorders/matnwb/refs/heads/gh-badges/.github/badges/tested_on.svg)
![MATLAB Versions Tested](https://raw.githubusercontent.com/NeurodataWithoutBorders/matnwb/refs/heads/gh-badges/.github/badges/v${{ inputs.version }}/tested_with.svg)
5 changes: 5 additions & 0 deletions .github/workflows/templates/contents_header_template.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
% MatNWB : NWB For MATLAB
% Version {{version_number}} (R2019b+) {{date_string}}
%
% Copyright (c) {{year_number}}, Neurodata Without Borders
% ---------------------------------------------
27 changes: 27 additions & 0 deletions Contents.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
% MatNWB : NWB For MATLAB
% Version 2.7.0 (R2019b+) 19-Nov-2024
%
% Copyright (c) 2024, Neurodata Without Borders
% ---------------------------------------------
%
% Functions:
%
% NwbFile - Root object representing an NWB file.
% generateCore - Generate Matlab classes from NWB core schema files
% generateExtension - Generate Matlab classes from NWB extension schema file
% inspectNwbFile - Run nwbinspector on the specified NWB file
% nwbClearGenerated - Clear generated class files.
% nwbExport - Writes an NWB file.
% nwbInstallExtension - Installs a specified NWB extension.
% nwbRead - Read an NWB file.
% nwbtest - Run MatNWB test suite.
%
% Namespaces:
% types - Namespace containing classes for neurodata types.
% util - Namespace containing utility functions.
%
% Folders:
%
% tutorials - Livescript tutorials demonstrating how to work with MatNWB
% namespaces - Cached namespace specifications
% nwb-schema - Source NWB specification schemas for different NWB versions
2 changes: 2 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,5 @@ Contents

pages/developer/contributing
pages/developer/documentation
pages/developer/releases

20 changes: 20 additions & 0 deletions docs/source/pages/developer/releases.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.. _how-to-create-release:

How to Create a New Release
===========================

1. **Navigate to the** `"Actions" <https://github.com/NeurodataWithoutBorders/matnwb/actions/workflows/prepare_release.yml>`_ **tab** in the MatNwb repository on GitHub.

2. **Click "Run workflow"**, then:
- Enter the desired version number in ``major.minor.patch`` format (e.g., ``2.8.0``).
- Click the **Run workflow** button to start the process.

3. **Monitor the workflow** as it runs across multiple MATLAB and OS configurations. The workflow is successful if:
- The version string is valid.
- All tests pass successfully.

4. **Confirm the draft release** once the workflow completes:
- A new tag (matching your version number) is pushed to the repository.
- A draft release is automatically generated with updated badges and the revised ``Contents.m`` file.

5. **(Optional) Finalize the release** by editing the draft release in GitHub’s "Releases" section, adding any additional details, and clicking **"Publish release"**.