From 5cd6af6966786f150fc27b1b478a6e66811430dc Mon Sep 17 00:00:00 2001 From: Lawrence <33462079+lawrence-mbf@users.noreply.github.com> Date: Sat, 2 Nov 2024 13:19:13 +0000 Subject: [PATCH] Convert Azure Pipeline to Github Actions (#543) * add test python requirements * migrate azure pipeline to github actions * Fix test workflow syntax - properly embed bash calls - fix artifact reference name - try to fix MATLAB test discovery * attempt to fix python setup * switch run-test to run-command * try to upload to codecov * Fix CI testing Use version of MATLAB that supports hdf5 dynamically loaded filters. * check ci env setting * fix debug pipeline * more env fixing * fix expected error test id * remove debug prints from ci * add source files to download repo * try different test suite * try different test suite (again) * Try using MATLAB R2024a for tests in workflow * Give test workflow a shorter name * Add codecov settings file * Update versions of dependent actions to latest versions * Update test badge in README.md * Rename utilities folder to tools * Add codespell workflow --------- Co-authored-by: ehennestad Co-authored-by: Ben Dichter --- +tests/requirements.txt | 2 + .codespellrc | 2 +- .github/.codecov.yaml | 12 +++ ..._action.yml => add_issues_to_projects.yml} | 0 .github/workflows/run_codespell.yml | 46 +++++++++++ .github/workflows/run_tests.yml | 82 +++++++++++++++++++ README.md | 4 +- azure-pipelines.yml | 48 ----------- tools/maintenance/validateCodecovSettings.m | 16 ++++ 9 files changed, 162 insertions(+), 50 deletions(-) create mode 100644 +tests/requirements.txt create mode 100644 .github/.codecov.yaml rename .github/workflows/{project_action.yml => add_issues_to_projects.yml} (100%) create mode 100644 .github/workflows/run_codespell.yml create mode 100644 .github/workflows/run_tests.yml delete mode 100644 azure-pipelines.yml create mode 100644 tools/maintenance/validateCodecovSettings.m diff --git a/+tests/requirements.txt b/+tests/requirements.txt new file mode 100644 index 00000000..da0e7629 --- /dev/null +++ b/+tests/requirements.txt @@ -0,0 +1,2 @@ +pynwb +hdf5plugin \ No newline at end of file diff --git a/.codespellrc b/.codespellrc index 7120bfee..65f2c912 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,3 +1,3 @@ [codespell] -skip = *.html,*logo_matnwb.svg,*fastsearch.m,*.yaml,*UpdateThirdPartyFromUpstream.sh,*testResults.xml +skip = *.html,*logo_matnwb.svg,*fastsearch.m,*.yaml,*testResults.xml ignore-words-list = DNE,nd,whos diff --git a/.github/.codecov.yaml b/.github/.codecov.yaml new file mode 100644 index 00000000..34edfa4d --- /dev/null +++ b/.github/.codecov.yaml @@ -0,0 +1,12 @@ +coverage: + range: "90...100" + status: + project: + default: + target: 90 # Set the desired coverage target as 90% + threshold: 1 # Allowable drop in coverage + patch: + default: + # 75% of the changed code must be covered by tests + threshold: 25 + only_pulls: true diff --git a/.github/workflows/project_action.yml b/.github/workflows/add_issues_to_projects.yml similarity index 100% rename from .github/workflows/project_action.yml rename to .github/workflows/add_issues_to_projects.yml diff --git a/.github/workflows/run_codespell.yml b/.github/workflows/run_codespell.yml new file mode 100644 index 00000000..127857ba --- /dev/null +++ b/.github/workflows/run_codespell.yml @@ -0,0 +1,46 @@ +# Note: This workflow allows specifying a custom location for the Codespell +# configuration file by defining CONFIG_FILE as an environment variable. +# A defined subset of options is extracted from this file and passed to the +# Codespell action. This also ensures that the output of the codespell action +# prints out the values of these options. +# Todo: Generalize the extraction of codespell input arguments/options. + +name: Codespell + +on: + pull_request: + branches: + - master + push: + branches-ignore: + - master + +jobs: + codespell: + name: Check for spelling errors + runs-on: ubuntu-latest + env: + CONFIG_FILE: .codespellrc + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Extract codespell configurations from configuration file + id: config + run: | + # Extract 'skip' value from the config file, excluding 'skip = ' part + skip=$(grep -E '^skip' "$CONFIG_FILE" | sed 's/^skip *= *//') + + # Extract 'ignore-words-list' value from the config file, excluding 'ignore-words-list = ' part + ignore_words=$(grep -E '^ignore-words-list' "$CONFIG_FILE" | sed 's/^ignore-words-list *= *//') + + # Export values as environment variables + echo "SKIP=$skip" >> $GITHUB_ENV + echo "IGNORE_WORDS_LIST=$ignore_words" >> $GITHUB_ENV + + - name: Codespell + uses: codespell-project/actions-codespell@v2 + with: + skip: "${{ env.SKIP }}" + ignore_words_list: "${{ env.IGNORE_WORDS_LIST }}" diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml new file mode 100644 index 00000000..023ee852 --- /dev/null +++ b/.github/workflows/run_tests.yml @@ -0,0 +1,82 @@ +# Run and publish MATLAB tests with coverage +name: Run tests + +on: + pull_request: + branches: + - master + paths-ignore: + - "*.md" + - "*.codespellrc" + - ".github/**" + push: + branches: + - master + +jobs: + run_tests: + name: Run MATLAB tests + runs-on: ubuntu-latest + steps: + - name: check out repository + uses: actions/checkout@v4 + - name: install python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: configure python env + run: | + python -m pip install -U pip + pip install -r +tests/requirements.txt + echo "HDF5_PLUGIN_PATH=$(python -c "import hdf5plugin; print(hdf5plugin.PLUGINS_PATH)")" >> "$GITHUB_ENV" + - name: install MATLAB + uses: matlab-actions/setup-matlab@v2 + with: + release: R2024a # this is necessary to test dynamic filters + - name: run tests + uses: matlab-actions/run-command@v2 + with: + command: results = assertSuccess(nwbtest); assert(~isempty(results), 'No tests ran'); + - name: upload JUnit results + uses: actions/upload-artifact@v4 + with: + name: test-results + path: testResults.xml + retention-days: 1 + - name: upload coverage results + uses: actions/upload-artifact@v4 + with: + name: test-coverage + path: ./coverage.xml + publish_junit: + name: Publish JUnit Test Results + runs-on: ubuntu-latest + if: ${{ always() }} + needs: [run_tests] + steps: + - name: retrieve result files + uses: actions/download-artifact@v4 + with: + name: test-results + - name: publish results + uses: mikepenz/action-junit-report@v4 + with: + report_paths: 'testResults.xml' + publish_coverage: + name: Publish Cobertura Test Coverage + runs-on: ubuntu-latest + needs: [run_tests] + steps: + - name: check out repository + uses: actions/checkout@v4 + - name: retrieve code coverage files + uses: actions/download-artifact@v4 + with: + name: test-coverage + - name: publish on Codecov + uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.xml + name: codecov-matnwb + verbose: true \ No newline at end of file diff --git a/README.md b/README.md index 7f31926e..f8470a3f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ ![MatNWB Logo](logo/logo_matnwb_small.png) [![Open in MATLAB Online](https://www.mathworks.com/images/responsive/global/open-in-matlab-online.svg)](https://matlab.mathworks.com/open/github/v1?repo=NeurodataWithoutBorders/matnwb&file=tutorials/basicUsage.mlx) -[![codecov](https://codecov.io/gh/NeurodataWithoutBorders/matnwb/branch/master/graph/badge.svg?token=apA7F24NsO)](https://codecov.io/gh/NeurodataWithoutBorders/matnwb) ![Azure DevOps tests](https://img.shields.io/azure-devops/tests/NeurodataWithoutBorders/matnwb/4) +[![codecov](https://codecov.io/gh/NeurodataWithoutBorders/matnwb/branch/master/graph/badge.svg?token=apA7F24NsO)](https://codecov.io/gh/NeurodataWithoutBorders/matnwb) +[![Run tests](https://github.com/NeurodataWithoutBorders/matnwb/actions/workflows/run_tests.yml/badge.svg)](https://github.com/NeurodataWithoutBorders/matnwb/actions/workflows/run_tests.yml?query=event%3Apush+branch%3Amaster) +[![Codespell](https://github.com/NeurodataWithoutBorders/matnwb/actions/workflows/run_codespell.yml/badge.svg?branch=master)](https://github.com/NeurodataWithoutBorders/matnwb/actions/workflows/run_codespell.yml?query=event%3Apush+branch%3Amaster) MatNWB is a Matlab interface for reading and writing Neurodata Without Borders (NWB) 2.x files. diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 33b11d33..00000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,48 +0,0 @@ -trigger: -- master - -pool: - vmImage: 'ubuntu-latest' - -steps: - - task: InstallMATLAB@0 - # default to latest version of Matlab installed - #inputs: - # release: R2017a - - checkout: self - - - task: UsePythonVersion@0 - inputs: - versionSpec: '3.8' - architecture: 'x64' - - - bash: | - python -m pip install --upgrade pip - pip install pynwb - pip install hdf5plugin - echo "##vso[task.setvariable variable=plugin_path]$(python -c "import hdf5plugin; print(hdf5plugin.PLUGINS_PATH)")" - echo "##vso[task.setvariable variable=pynwb_path]$(python -c "import pynwb; print(pynwb.__path__[0])")" - displayName: 'Install PyNWB' - - - task: RunMATLABCommand@0 - inputs: - command: "results = assertSuccess(nwbtest); assert(~isempty(results), 'No tests ran');" - env: - HDF5_PLUGIN_PATH: $(plugin_path) - PYNWB_PATH: $(pynwb_path) - - - task: PublishTestResults@2 - condition: succeededOrFailed() - inputs: - testResultsFiles: testResults.xml - - - task: PublishCodeCoverageResults@1 - inputs: - codeCoverageTool: Cobertura - summaryFileLocation: coverage.xml - - - script: | - bash <(curl -s https://codecov.io/bash) - displayName: 'Upload coverage to codecov' - - diff --git a/tools/maintenance/validateCodecovSettings.m b/tools/maintenance/validateCodecovSettings.m new file mode 100644 index 00000000..2bcd41bb --- /dev/null +++ b/tools/maintenance/validateCodecovSettings.m @@ -0,0 +1,16 @@ +function validateCodecovSettings() +% validateCodecovSettings Validate a codecov settings file. +% +% Note: This is a utility function developer's can use to check the +% codecov settings file in .github/.codecov.yaml + + sysCommand = sprintf("curl -X POST --data-binary @%s https://codecov.io/validate", ... + fullfile(misc.getMatnwbDir, '.github', '.codecov.yaml')); + + [status, message] = system(sysCommand); + + assert(status == 0, 'Curl command failed') + + assert(contains(message, 'Valid!'), ... + 'Codecov settings file is invalid') +end