From da91f6d3c68941e9b2210e9fd501ff4c4779e478 Mon Sep 17 00:00:00 2001 From: Patrick Schuenke <37338697+schuenke@users.noreply.github.com> Date: Wed, 5 Feb 2025 12:15:21 +0100 Subject: [PATCH] Split test workflow to fix permission issue (#2) --- .github/workflows/push_pr.yml | 83 ------------------------ .github/workflows/pytest.yml | 70 ++++++++++++++++++++ .github/workflows/report_pytest.yml | 99 +++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 83 deletions(-) delete mode 100644 .github/workflows/push_pr.yml create mode 100644 .github/workflows/pytest.yml create mode 100644 .github/workflows/report_pytest.yml diff --git a/.github/workflows/push_pr.yml b/.github/workflows/push_pr.yml deleted file mode 100644 index e8357ebc..00000000 --- a/.github/workflows/push_pr.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Run code tests on push and pull requests -on: - push: - branches: - - master - pull_request: - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -permissions: - contents: read - pull-requests: write - -jobs: - tests: - name: Code tests - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] - include-sigpy: [true, false] - - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Cache pip dependencies - uses: actions/cache@v3 - with: - path: ~/.cache/pip - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }} - restore-keys: | - ${{ runner.os }}-pip- - - - name: Install PyPulseq and dependencies - run: | - pip install --upgrade --upgrade-strategy eager .[test] - if [ ${{ matrix.include-sigpy }} == "true" ]; then - pip install sigpy - fi - - - name: Install PyTest GitHub Annotation Plugin - run: pip install pytest-github-actions-annotate-failures - - - name: Run PyTest and Generate Coverage Report - run: | - if [ ${{ matrix.include-sigpy }} == "true" ]; then - pytest -m "not slow" --junitxml=pytest.xml \ - --cov-report=term-missing:skip-covered --cov=sequences | tee pytest-coverage.txt - else - pytest -m "not slow and not sigpy" --junitxml=pytest.xml \ - --cov-report=term-missing:skip-covered --cov=sequences | tee pytest-coverage.txt - fi - continue-on-error: ${{ matrix.include-sigpy }} - - - name: Verify PyTest XML Output - run: | - if [ ! -f pytest.xml ]; then - echo "PyTest XML report not found. Please check the previous 'Run PyTest' step for errors." - exit 1 - fi - - - name: Post PyTest Coverage Comment - id: coverageComment - uses: MishaKav/pytest-coverage-comment@v1.1.53 - with: - pytest-coverage-path: ./pytest-coverage.txt - junitxml-path: ./pytest.xml - - - name: Set Pipeline Status Based on Test Results - if: steps.coverageComment.outputs.errors != 0 || steps.coverageComment.outputs.failures != 0 - uses: actions/github-script@v7 - with: - script: | - core.setFailed("PyTest workflow failed with ${{ steps.coverageComment.outputs.errors }} errors and ${{ steps.coverageComment.outputs.failures }} failures.") - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - - # Cancel in-progress runs when a new workflow with the same group name is triggered - cancel-in-progress: true diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 00000000..f5175c35 --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,70 @@ +name: PyTest + +on: + pull_request: + push: + branches: + - master + workflow_dispatch: + +jobs: + test: + name: Code tests + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] + include-sigpy: [true] + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Cache pip dependencies + uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install PyPulseq and dependencies + run: | + pip install --upgrade --upgrade-strategy eager .[test] + if [ ${{ matrix.include-sigpy }} == "true" ]; then + pip install sigpy + fi + + - name: Install PyTest GitHub Annotation Plugin + run: pip install pytest-github-actions-annotate-failures + + - name: Run PyTest and Generate Coverage Report + shell: bash + run: | + if [ ${{ matrix.include-sigpy }} == "true" ]; then + pytest --junitxml=pytest.xml \ + --cov-report=term-missing:skip-covered --cov=pypulseq | tee pytest-coverage.txt + else + pytest -m "not sigpy" --junitxml=pytest.xml \ + --cov-report=term-missing:skip-covered --cov=pypulseq | tee pytest-coverage.txt + fi + + - name: Upload PyTest Coverage Report + if: always() + uses: actions/upload-artifact@v4 + with: + name: pytest-report-${{ matrix.python-version }}-${{ matrix.include-sigpy }} + path: | + pytest-coverage.txt + pytest.xml + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + + # Cancel in-progress runs when a new workflow with the same group name is triggered + cancel-in-progress: true diff --git a/.github/workflows/report_pytest.yml b/.github/workflows/report_pytest.yml new file mode 100644 index 00000000..af3ba693 --- /dev/null +++ b/.github/workflows/report_pytest.yml @@ -0,0 +1,99 @@ +name: Report PyTest + +on: + workflow_run: + workflows: + - PyTest + types: + - completed + +jobs: + coverage_report_pr: + name: Coverage report PR + if: ${{ github.event.workflow_run.event == 'pull_request' }} + runs-on: ubuntu-latest + permissions: + actions: read + pull-requests: write + steps: + # use the results of python 3.12, consider this as target platform + - name: Download PyTest report artifact for Python 3.12 + uses: actions/download-artifact@v4 + with: + name: pytest-report-3.12-true + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Get PR number + id: pr-context + env: + # Token required for GH CLI: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Best practice for scripts is to reference via ENV at runtime. Avoid using the expression syntax in the script content directly: + PR_TARGET_REPO: ${{ github.repository }} + # If the PR is from a fork, prefix it with `:`, otherwise only the PR branch name is relevant: + PR_BRANCH: |- + ${{ + (github.event.workflow_run.head_repository.owner.login != github.event.workflow_run.repository.owner.login) + && format('{0}:{1}', github.event.workflow_run.head_repository.owner.login, github.event.workflow_run.head_branch) + || github.event.workflow_run.head_branch + }} + # Query the PR number by repo + branch, then assign to step output: + run: | + gh pr view --repo "${PR_TARGET_REPO}" "${PR_BRANCH}" \ + --json 'number' --jq '"number=\(.number)"' \ + >> "${GITHUB_OUTPUT}" + + - name: Post PyTest Coverage Comment + id: coverage_comment + uses: MishaKav/pytest-coverage-comment@v1.1.53 + with: + issue-number: ${{ steps.pr-context.outputs.number }} + pytest-coverage-path: pytest-coverage.txt + junitxml-path: pytest.xml + + - name: Post Failure Comment if Coverage Comment failed + # if there is no data the comment action does not fail but has an empty output + if: steps.coverage_comment.outputs.coverageHtml == '' + uses: edumserrano/find-create-or-update-comment@v3 + with: + issue-number: ${{ steps.pr-context.outputs.number }} + body-includes: "" + comment-author: "github-actions[bot]" + body: | + + ### :x: PyTest Coverage Report was not found + + Check the PyTest Workflow + edit-mode: replace + + coverage_report_push: + name: Coverage report PUSH + if: ${{ github.event.workflow_run.event == 'push' && github.event.workflow_run.head_branch == 'master' }} + runs-on: ubuntu-latest + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + name: pytest-report-3.12-true + + - name: Post PyTest Coverage Comment on push + id: coverage_comment + uses: MishaKav/pytest-coverage-comment@v1.1.53 + with: + pytest-coverage-path: pytest-coverage.txt + junitxml-path: pytest.xml + + # Todo: create a GIST and GIST secret to enable badge creation + # - name: Create Coverage Badge on push to master + # uses: schneegans/dynamic-badges-action@v1.7.0 + # with: + # auth: ${{ secrets.GIST_SECRET }} + # gistID: xxx + # filename: coverage.json + # label: Coverage Report + # message: ${{ steps.coverage_comment.outputs.coverage }} + # color: ${{ steps.coverage_comment.outputs.color }} + # namedLogo: python