From c84055289f1b841fe3fd251f766afeb61871c1e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Cl=C3=A9net?= Date: Fri, 24 Feb 2023 16:57:59 +0100 Subject: [PATCH] [CI] GitHub Actions workflows and GitLab CI example script --- .github/workflows/code_quality.yml | 13 ++- .github/workflows/pipeline_tests.yml | 70 ++++++++++++ .github/workflows/test_changes.yml | 42 ++++++++ .github/workflows/unit_tests.yml | 39 +++++++ .gitlab-ci.yml | 154 +++++++++++++++++++++++++++ docs/ci-cd.md | 29 ++--- 6 files changed, 317 insertions(+), 30 deletions(-) create mode 100644 .github/workflows/pipeline_tests.yml create mode 100644 .github/workflows/test_changes.yml create mode 100644 .github/workflows/unit_tests.yml create mode 100644 .gitlab-ci.yml diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index 77495dce..2d5c8730 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -1,3 +1,5 @@ +## Disclaimer - This GitHub Actions workflow performs a static analysis of the python code. + # Name the workflow name: code_quality @@ -12,21 +14,18 @@ jobs: # Name of the job running pylint pylint: - # Define the OS and the python versions to use + # Define the OS runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.8', '3.9', '3.10'] # Steps that define the job steps: - name: Checkout repository uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python uses: actions/setup-python@v3 with: - python-version: ${{ matrix.python-version }} + python-version: 3.9 - name: Install dependencies run: | @@ -41,7 +40,7 @@ jobs: - name: Archive pylint results uses: actions/upload-artifact@v3 with: - name: pylint-reports-python${{ matrix.python-version }} + name: pylint-reports-python path: | pylint_report_narps_open.txt pylint_report_tests.txt diff --git a/.github/workflows/pipeline_tests.yml b/.github/workflows/pipeline_tests.yml new file mode 100644 index 00000000..8b474aaf --- /dev/null +++ b/.github/workflows/pipeline_tests.yml @@ -0,0 +1,70 @@ +## Disclaimer - This GitHub Actions workflow runs all the tests for changed pipelines. + +# Name the workflow +name: pipeline_tests + +# Define when it runs (on PR when code for a pipeline changes) +on: + pull_request: + paths: + - 'narps_open/pipelines/**' + +# Jobs that define the workflow +jobs: + + # A job to list the tests to be run + identify-tests: + runs-on: ubuntu-latest + outputs: + tests: ${{ steps.identify.outputs.tests }} + steps: + - name: Checkout main branch for comparison + uses: actions/checkout@v3 + with: + ref: main + fetch-depth: 0 + + - name: Checkout current branch + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Create a list of tests for changed pipelines + id: identify + run: | + # Loop through modified files + for file in $(git diff --name-only remotes/origin/main...$GITHUB_SHA) + do + # List team id corresponding to team_* files + if [[ "$file" =~ .*"narps_open/pipelines/team_".* ]]; then + echo "Modified pipeline = $file" + tmp=${file#*"team_"} # remove prefix ending in "team_" + team_id=${tmp%".py"*} # remove suffix starting with ".py" + # Populate the list of test files + test_files="$test_files tests/pipelines/test_team_$team_id.py" + fi + done + # Send the test list as job output + echo "tests=$test_files" >> $GITHUB_OUTPUT + + # A job to run the identified tests + pytest: + needs: identify-tests + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Python 3.9 + uses: actions/setup-python@v3 + with: + python-version: 3.9 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest + pip install . + + - name: Collect tests with pytest + run: pytest --collect-only -q ${{ needs.identify-tests.outputs.tests }} diff --git a/.github/workflows/test_changes.yml b/.github/workflows/test_changes.yml new file mode 100644 index 00000000..94ea183e --- /dev/null +++ b/.github/workflows/test_changes.yml @@ -0,0 +1,42 @@ +## Disclaimer - This GitHub Actions workflow runs all the changed tests for the project. + +# Name the workflow +name: test_changes + +# Define when it runs (on PR when a test changes) +on: + pull_request: + paths: + - 'tests/**' + +# Jobs that define the workflow +jobs: + + # A job to list the tests to be run + pytest: + runs-on: ubuntu-latest + steps: + - name: Checkout main branch for comparison + uses: actions/checkout@v3 + with: + ref: main + fetch-depth: 0 + + - name: Checkout current branch + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Create a list of tests for changed tests + id: identify + run: | + echo "tests=$(git diff --name-only remotes/origin/main...$GITHUB_SHA)" >> $GITHUB_OUTPUT + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest + pip install . + + - name: Collect tests with pytest + run: pytest --collect-only -q ${{ steps.identify.outputs.tests }} diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml new file mode 100644 index 00000000..5723c289 --- /dev/null +++ b/.github/workflows/unit_tests.yml @@ -0,0 +1,39 @@ +## Disclaimer - This GitHub Actions workflow runs all the unit tests for the project. + +# Name the workflow +name: unit_testing + +# Define when it runs (on PR when narps_open files change) +on: + pull_request: + paths: + - 'narps_open/**' + - '!narps_open/pipelines/**' + +# Jobs that define the workflow +jobs: + # Name of the job running unit tests + pytest: + + # Define the runner for this job + runs-on: ubuntu-latest + + # Steps that define the job + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Python 3.9 + uses: actions/setup-python@v3 + with: + python-version: 3.9 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest + pip install . + + - name: Collect tests with pytest + run: | + pytest --collect-only -q --ignore=tests/pipelines/ tests/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..9800e6cf --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,154 @@ +## Disclaimer - This GitLab CI script allow contributors to perform CI on + +# We assume the runner uses Docker as executor +# We assume that the following images are available on the system : +# - elodiegermani/open_pipeline + +default: + # Run all scripts in a docker container based on this image + image: elodiegermani/open_pipeline + +before_script: + # Activate conda virtual environment + - source activate neuro + + # Install the narps_open python package from the source code + - pip install . + +stages: + - code_quality + - testing + +# Static analysis of the project's code +pylint_job: + stage: code_quality + script: + # Install pylint + - pip install pylint + + # Run pylint + - pylint --exit-zero narps_open > pylint_report_narps_open.txt + - pylint --exit-zero tests > pylint_report_tests.txt + + artifacts: + when: always + paths: + - pylint_report_narps_open.txt + - pylint_report_tests.txt + - todos_narps_open.txt + - todos_tests.txt + +# Running tests for narps_open (except pipelines) +unit_tests-job: + stage: testing + script: + # Install pytest & coverage + - pip install pytest pytest-cov + + # Run tests and produce reports + - coverage run -m pytest --junit-xml=pytest_report.xml --ignore=tests/pipelines/ tests/ + - coverage report + - coverage xml + + artifacts: + when: on_success + reports: + junit: pytest_report.xml + coverage_report: + coverage_format: cobertura + path: coverage.xml + + rules: + # If something changed in narps_open (except in narps_open/pipelines) + - if: $CI_COMMIT_BRANCH + changes: + compare_to: 'refs/heads/main' + paths: + - 'narps_open/(?!pipelines)*' + +# Running tests for pipelines +pipeline_tests-job: + stage: testing + variables: + PIPELINES_TEST_FILES : "" + #GIT_STRATEGY: clone # So that we can access the main branch for git diff purpose + script: + # Install pytest & coverage + - pip install pytest pytest-cov + + - git switch main + - git switch $CI_COMMIT_BRANCH + + # List test files corresponding to modified files + - | + for file in $(git diff --name-only origin/main...$CI_COMMIT_BRANCH) + do + if [[ "$file" =~ .*"pipeline".* ]]; then + echo "Modified pipeline = $file" + + tmp=${file#*"team_"} # remove prefix ending in "team_" + team_id=${tmp%".py"*} # remove suffix starting with ".py" + + PIPELINES_TEST_FILES="$PIPELINES_TEST_FILES tests/pipelines/test_team_$team_id.py" + fi + done + + - echo "$PIPELINES_TEST_FILES" + + # Run tests and produce reports + - coverage run -m pytest --junit-xml=pytest_report.xml "$PIPELINES_TEST_FILES" + - coverage report + - coverage xml + + artifacts: + when: on_success + reports: + junit: pytest_report.xml + coverage_report: + coverage_format: cobertura + path: coverage.xml + + rules: + # If something changed in narps_open/pipelines + - if: $CI_COMMIT_BRANCH + changes: + compare_to: 'refs/heads/main' + paths: + - 'narps_open/pipelines*' + +# Running tests that changed +test_changes-job: + stage: testing + variables: + TEST_FILES : "" + #GIT_STRATEGY: clone # So that we can access the main branch for git diff purpose + script: + # Install pytest & coverage + - pip install pytest pytest-cov + + - git switch main + - git switch $CI_COMMIT_BRANCH + + # List test files corresponding to modified files + - TEST_FILES=$(git diff --name-only origin/main...$CI_COMMIT_BRANCH) + + # Run tests and produce reports + - coverage run -m pytest --junit-xml=pytest_report.xml "$TEST_FILES" + - coverage report + - coverage xml + + artifacts: + when: on_success + reports: + junit: pytest_report.xml + coverage_report: + coverage_format: cobertura + path: coverage.xml + + rules: + # If something changed in narps_open/pipelines + - if: $CI_COMMIT_BRANCH + changes: + compare_to: 'refs/heads/main' + paths: + - 'tests/*' diff --git a/docs/ci-cd.md b/docs/ci-cd.md index 458f7bba..05a536c5 100644 --- a/docs/ci-cd.md +++ b/docs/ci-cd.md @@ -32,29 +32,12 @@ Furthermore, you can always [prevent GitHub from running workflows](https://docs For now, the following workflows are set up: -* [code_quality.yml](/.github/workflows/code_quality.yml) - * **What does it do ?** It performs a static analysis of the python code (see the [testing](/docs/testing.md) topic of the documentation for more information). - * **When is it launched ?** For every push (except ) if there are changes on `.py` files. - * **Where does it run ?** On GitHub servers. - * **How can I see the results ?** Outputs (logs of pylint) are stored as [downloadable artifacts](https://docs.github.com/en/actions/managing-workflow-runs/downloading-workflow-artifacts) during 15 days after the push. - -* [pipelines.yml](/.github/workflows/pipelines.yml) - * **What does it do ?** It runs all the tests for changed pipelines. - * **When is it launched ?** For every pull request, if a pipeline file changed inside `narps_open/pipelines/`. - * **Where does it run ?** On Empenn runners. - * **How can I see the results ?** Outputs (logs of pytest) are stored as downloadable artifacts during 15 days after the push. - -* [tests.yml](/.github/workflows/tests.yml) - * **What does it do ?** It runs all the changed tests for the project. - * **When is it launched ?** For every pull request, if a test file changed inside `tests/`. - * **Where does it run ?** On Empenn runners. - * **How can I see the results ?** Outputs (logs of pytest) are stored as downloadable artifacts during 15 days after the push. - -* [unit_testing.yml](/.github/workflows/unit_testing.yml) - * **What does it do ?** It runs all the unit tests for the project (see the [testing](/docs/testing.md) topic of the documentation for more information). - * **When is it launched ?** For every pull request, if a file changed inside `narps_open/` other than in `narps_open/pipeline`. - * **Where does it run ?** On Empenn runners. - * **How can I see the results ?** Outputs (logs of pytest) are stored as downloadable artifacts during 15 days after the push. +| Name | File | What does it do ? | When is it launched ? | Where does it run ? | How can I see the results ? | +| ----------- | ----------- | ----------- | ----------- | ----------- | ----------- | +| code_quality | [code_quality.yml](/.github/workflows/code_quality.yml) | A static analysis of the python code (see the [testing](/docs/testing.md) topic of the documentation for more information). | For every push if there are changes on `.py` files. | On GitHub servers. | Outputs (logs of pylint) are stored as [downloadable artifacts](https://docs.github.com/en/actions/managing-workflow-runs/downloading-workflow-artifacts) during 15 days after the push. | +| pipeline_tests | [pipeline_tests.yml](/.github/workflows/pipelines.yml) | Runs all the tests for changed pipelines. | For every pull request, if a pipeline file changed inside `narps_open/pipelines/`. | On Empenn runners. | Outputs (logs of pytest) are stored as downloadable artifacts during 15 days after the push. | +| test_changes | [tests.yml](/.github/workflows/test_changes.yml) | It runs all the changed tests for the project. | For every pull request, if a test file changed inside `tests/`. | On Empenn runners. | Outputs (logs of pytest) are stored as downloadable artifacts during 15 days after the push. | +| unit_testing | [unit_testing.yml](/.github/workflows/unit_testing.yml) | It runs all the unit tests for the project (see the [testing](/docs/testing.md) topic of the documentation for more information). | For every pull request, if a file changed inside `narps_open/` other than in `narps_open/pipeline`. | On Empenn runners. | Outputs (logs of pytest) are stored as downloadable artifacts during 15 days after the push. | ### Security