diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..1b5ad18 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,187 @@ +name: Weekly global Tool Linting and Tests +on: + schedule: + # Run at midnight every monday + - cron: '0 0 * * 1' + repository_dispatch: + types: [run-all-tool-tests-command] +env: + GALAXY_FORK: galaxyproject + GALAXY_BRANCH: release_21.05 + MAX_CHUNKS: 40 +jobs: + setup: + name: Setup cache and determine changed repositories + if: github.repository_owner == 'galaxyproject' + runs-on: ubuntu-latest + outputs: + galaxy-head-sha: ${{ steps.get-galaxy-sha.outputs.galaxy-head-sha }} + fork: ${{ steps.get-fork-branch.outputs.fork }} + branch: ${{ steps.get-fork-branch.outputs.branch }} + repository-list: ${{ steps.discover.outputs.repository-list }} + chunk-count: ${{ steps.discover.outputs.chunk-count }} + chunk-list: ${{ steps.discover.outputs.chunk-list }} + strategy: + matrix: + python-version: ['3.7'] + steps: + - name: Add reaction + if: ${{ github.event.client_payload.slash_command.command == 'run-all-tool-tests' }} + uses: peter-evans/create-or-update-comment@v1 + with: + token: ${{ secrets.PAT }} + repository: ${{ github.event.client_payload.github.payload.repository.full_name }} + comment-id: ${{ github.event.client_payload.github.payload.comment.id }} + reaction-type: hooray + - name: Set galaxy fork and branch + id: get-fork-branch + run: | + TMP="${{ github.event.client_payload.slash_command.args.named.fork }}" + echo "::set-output name=fork::${TMP:-$GALAXY_FORK}" + TMP="${{ github.event.client_payload.slash_command.args.named.branch }}" + echo "::set-output name=branch::${TMP:-$GALAXY_BRANCH}" + - name: Determine latest commit in the Galaxy repo + id: get-galaxy-sha + run: echo "::set-output name=galaxy-head-sha::$(git ls-remote https://github.com/${{ steps.get-fork-branch.outputs.fork }}/galaxy refs/heads/${{ steps.get-fork-branch.outputs.branch }} | cut -f1)" + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v2 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ steps.get-galaxy-sha.outputs.galaxy-head-sha }} + # Install the `wheel` package so that when installing other packages which + # are not available as wheels, pip will build a wheel for them, which can be cached. + - name: Install wheel + run: pip install wheel + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + - name: Fake a Planemo run to update cache and determine commit range, repositories, and chunks + uses: galaxyproject/planemo-ci-action@v1 + id: discover + with: + create-cache: ${{ steps.cache-pip.outputs.cache-hit != 'true' || steps.cache-planemo.outputs.cache-hit != 'true' }} + galaxy-fork: ${{ steps.get-fork-branch.outputs.fork }} + galaxy-branch: ${{ steps.get-fork-branch.outputs.branch }} + max-chunks: ${{ env.MAX_CHUNKS }} + python-version: ${{ matrix.python-version }} + - name: Show repository list + run: echo '${{ steps.discover.outputs.repository-list }}' + - name: Show chunks + run: | + echo 'Using ${{ steps.discover.outputs.chunk-count }} chunks (${{ steps.discover.outputs.chunk-list }})' + + test: + name: Test tools + # This job runs on Linux + runs-on: ubuntu-latest + needs: setup + if: ${{ needs.setup.outputs.repository-list != '' }} + strategy: + fail-fast: false + matrix: + chunk: ${{ fromJson(needs.setup.outputs.chunk-list) }} + python-version: ['3.7'] + services: + postgres: + image: postgres:11 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + steps: + # checkout the repository + # and use it as the current working directory + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v2 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup.outputs.galaxy-head-sha }} + - name: Planemo test + uses: galaxyproject/planemo-ci-action@v1 + id: test + with: + mode: test + repository-list: ${{ needs.setup.outputs.repository-list }} + galaxy-fork: ${{ needs.setup.outputs.fork }} + galaxy-branch: ${{ needs.setup.outputs.branch }} + chunk: ${{ matrix.chunk }} + chunk-count: ${{ needs.setup.outputs.chunk-count }} + - uses: actions/upload-artifact@v2 + with: + name: 'Tool test output ${{ matrix.chunk }}' + path: upload + + # - combine the results of the test chunks (which will never fail due + # to `|| true`) and create a global test report as json and html which + # is provided as artifact + # - check if any tool test actually failed (by lookup in the combined json) + # and fail this step if this is the case + combine_outputs: + name: Combine chunked test results + needs: [setup, test] + strategy: + matrix: + python-version: ['3.7'] + # This job runs on Linux + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v2 + with: + path: artifacts + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v2 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup.outputs.galaxy-head-sha }} + - name: Combine outputs + uses: galaxyproject/planemo-ci-action@v1 + id: combine + with: + mode: combine + html-report: true + - uses: actions/upload-artifact@v2 + with: + name: 'All tool test results' + path: upload + - name: Create URL to the run output + if: ${{ github.event.client_payload.slash_command.command == 'run-all-tool-tests' }} + id: vars + run: echo "::set-output name=run-url::https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" + + - name: Create comment + if: ${{ github.event.client_payload.slash_command.command == 'run-all-tool-tests' }} + uses: peter-evans/create-or-update-comment@v1 + with: + token: ${{ secrets.PAT }} + repository: ${{ github.event.client_payload.github.payload.repository.full_name }} + issue-number: ${{ github.event.client_payload.github.payload.issue.number }} + body: | + Summary: + + ${{ steps.combine.outputs.statistics }} + + [Find all tool test results here][1] + + [1]: ${{ steps.vars.outputs.run-url }} + - name: Check outputs + uses: galaxyproject/planemo-ci-action@v1 + id: check + with: + mode: check diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 0000000..d44cd5f --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,367 @@ +name: Galaxy Tool Linting and Tests for push and PR +on: [push, pull_request] +env: + GALAXY_FORK: galaxyproject + GALAXY_BRANCH: release_21.05 + MAX_CHUNKS: 4 +jobs: + # the setup job does two things: + # 1. cache the pip cache and .planemo + # 2. determine the list of changed repositories + # it produces one artifact which contains + # - a file with the latest SHA from the chosen branch of the Galaxy repo + # - a file containing the list of changed repositories + # which are needed in subsequent steps. + setup: + name: Setup cache and determine changed repositories + runs-on: ubuntu-latest + outputs: + galaxy-head-sha: ${{ steps.get-galaxy-sha.outputs.galaxy-head-sha }} + repository-list: ${{ steps.discover.outputs.repository-list }} + tool-list: ${{ steps.discover.outputs.tool-list }} + chunk-count: ${{ steps.discover.outputs.chunk-count }} + chunk-list: ${{ steps.discover.outputs.chunk-list }} + strategy: + matrix: + python-version: ['3.7'] + steps: + - name: Print github context properties + run: | + echo 'event: ${{ github.event_name }}' + echo 'sha: ${{ github.sha }}' + echo 'ref: ${{ github.ref }}' + echo 'head_ref: ${{ github.head_ref }}' + echo 'base_ref: ${{ github.base_ref }}' + echo 'event.before: ${{ github.event.before }}' + echo 'event.after: ${{ github.event.after }}' + - name: Determine latest commit in the Galaxy repo + id: get-galaxy-sha + run: echo "::set-output name=galaxy-head-sha::$(git ls-remote https://github.com/${{ env.GALAXY_FORK }}/galaxy refs/heads/${{ env.GALAXY_BRANCH }} | cut -f1)" + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v2 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ steps.get-galaxy-sha.outputs.galaxy-head-sha }} + - name: Cache .planemo + uses: actions/cache@v2 + id: cache-planemo + with: + path: ~/.planemo + key: planemo_cache_py_${{ matrix.python-version }}_gxy_${{ steps.get-galaxy-sha.outputs.galaxy-head-sha }} + # Install the `wheel` package so that when installing other packages which + # are not available as wheels, pip will build a wheel for them, which can be cached. + - name: Install wheel + run: pip install wheel + - name: Install flake8 + run: pip install flake8 flake8-import-order + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Fake a Planemo run to update cache and determine commit range, repositories, and chunks + uses: galaxyproject/planemo-ci-action@v1 + id: discover + with: + create-cache: ${{ steps.cache-pip.outputs.cache-hit != 'true' || steps.cache-planemo.outputs.cache-hit != 'true' }} + galaxy-fork: ${{ env.GALAXY_FORK }} + galaxy-branch: ${{ env.GALAXY_BRANCH }} + max-chunks: ${{ env.MAX_CHUNKS }} + python-version: ${{ matrix.python-version }} + - name: Show commit range + run: echo '${{ steps.discover.outputs.commit-range }}' + - name: Show repository list + run: echo '${{ steps.discover.outputs.repository-list }}' + - name: Show tool list + run: echo '${{ steps.discover.outputs.tool-list }}' + - name: Show chunks + run: | + echo 'Using ${{ steps.discover.outputs.chunk-count }} chunks (${{ steps.discover.outputs.chunk-list }})' + + # Planemo lint the changed repositories + lint: + name: Lint tool-list + needs: setup + if: ${{ needs.setup.outputs.repository-list != '' || needs.setup.outputs.tool-list != '' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.7'] + steps: + # checkout the repository + # and use it as the current working directory + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v2 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup.outputs.galaxy-head-sha }} + - name: Planemo lint + uses: galaxyproject/planemo-ci-action@v1 + id: lint + with: + mode: lint + repository-list: ${{ needs.setup.outputs.repository-list }} + tool-list: ${{ needs.setup.outputs.tool-list }} + - uses: actions/upload-artifact@v2 + if: ${{ failure() }} + with: + name: 'Tool linting output' + path: lint_report.txt + + # flake8 of Python scripts in the changed repositories + flake8: + name: Lint Python scripts + needs: setup + if: ${{ needs.setup.outputs.repository-list != '' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.7'] + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v2 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup.outputs.galaxy-head-sha }} + - name: Install flake8 + run: pip install flake8 flake8-import-order + - name: Flake8 + run: echo '${{ needs.setup.outputs.repository-list }}' | xargs -d '\n' flake8 --output-file pylint_report.txt --tee + - uses: actions/upload-artifact@v2 + if: ${{ failure() }} + with: + name: 'Python linting output' + path: pylint_report.txt + + lintr: + name: Lint R scripts + needs: setup + if: ${{ needs.setup.outputs.repository-list != '' }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-20.04] + r-version: ['4.0.1'] + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + - uses: r-lib/actions/setup-r@master + with: + r-version: ${{ matrix.r-version }} + - name: Cache R packages + uses: actions/cache@v2 + with: + path: ${{ env.R_LIBS_USER }} + key: r_cache_${{ matrix.os }}_${{ matrix.r-version }} + - name: Install non-R lintr dependencies + run: sudo apt-get install libcurl4-openssl-dev + - name: Install lintr + run: | + install.packages('remotes') + remotes::install_cran("lintr") + shell: Rscript {0} + - name: Save repositories to file + run: echo '${{ needs.setup.outputs.repository-list }}' > repository_list.txt + - name: lintr + run: | + library(lintr) + linters <- with_defaults(line_length_linter = NULL, cyclocomp_linter = NULL, object_usage_linter = NULL) + con <- file("repository_list.txt", "r") + status <- 0 + while (TRUE) { + repo <- readLines(con, n = 1) + if (length(repo) == 0) { + break + } + lnt <- lint_dir(repo, relative_path=T, linters=linters) + if (length(lnt) > 0) { + status <- 1 + for (l in lnt) { + rel_path <- paste(repo, l$filename, sep="/") + write(paste(paste(rel_path, l$line_number, l$column_number, sep=":"), l$message), stderr()) + write(paste(paste(rel_path, l$line_number, l$column_number, sep=":"), l$message), "rlint_report.txt", append=TRUE) + } + } + } + quit(status = status) + shell: Rscript {0} + - uses: actions/upload-artifact@v2 + if: ${{ failure() }} + with: + name: 'R linting output' + path: rlint_report.txt + + # Planemo test the changed repositories, each chunk creates an artifact + # containing HTML and JSON reports for the executed tests + test: + name: Test tools + needs: setup + if: ${{ needs.setup.outputs.repository-list != '' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + chunk: ${{ fromJson(needs.setup.outputs.chunk-list) }} + python-version: ['3.7'] + services: + postgres: + image: postgres:11 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + steps: + # checkout the repository + # and use it as the current working directory + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v2 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup.outputs.galaxy-head-sha }} + - name: Cache .planemo + uses: actions/cache@v2 + id: cache-planemo + with: + path: ~/.planemo + key: planemo_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup.outputs.galaxy-head-sha }} + - name: Planemo test + uses: galaxyproject/planemo-ci-action@v1 + id: test + with: + mode: test + repository-list: ${{ needs.setup.outputs.repository-list }} + galaxy-fork: ${{ env.GALAXY_FORK }} + galaxy-branch: ${{ env.GALAXY_BRANCH }} + chunk: ${{ matrix.chunk }} + chunk-count: ${{ needs.setup.outputs.chunk-count }} + - uses: actions/upload-artifact@v2 + with: + name: 'Tool test output ${{ matrix.chunk }}' + path: upload + + # - combine the results of the test chunks (which will never fail due + # to `|| true`) and create a global test report as json and html which + # is provided as artifact + # - check if any tool test actually failed (by lookup in the combined json) + # and fail this step if this is the case + combine_outputs: + name: Combine chunked test results + needs: [setup, test] + if: ${{ needs.setup.outputs.repository-list != '' }} + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.7'] + steps: + - uses: actions/download-artifact@v2 + with: + path: artifacts + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v2 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup.outputs.galaxy-head-sha }} + - name: Combine outputs + uses: galaxyproject/planemo-ci-action@v1 + id: combine + with: + mode: combine + html-report: true + - uses: actions/upload-artifact@v2 + with: + name: 'All tool test results' + path: upload + - name: Check outputs + uses: galaxyproject/planemo-ci-action@v1 + id: check + with: + mode: check + + # deploy the tools to the toolsheds (first TTS for testing) + deploy: + name: Deploy + needs: [setup, lint, flake8, lintr, combine_outputs] + if: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' ) && github.repository_owner == 'galaxyproject' }} + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.7'] + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 1 + - uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v2 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup.outputs.galaxy-head-sha }} + - name: Deploy on testtoolshed + uses: galaxyproject/planemo-ci-action@v1 + with: + mode: deploy + repository-list: ${{ needs.setup.outputs.repository-list }} + shed-target: testtoolshed + shed-key: ${{ secrets.TTS_API_KEY }} + continue-on-error: true + - name: Deploy on toolshed + uses: galaxyproject/planemo-ci-action@v1 + with: + mode: deploy + repository-list: ${{ needs.setup.outputs.repository-list }} + shed-target: toolshed + shed-key: ${{ secrets.TS_API_KEY }} + + determine-success: + name: Check workflow success + needs: [setup, lint, flake8, lintr, combine_outputs] + if: ${{ always() && github.ref != 'refs/heads/master' && github.ref != 'refs/heads/main' }} + runs-on: ubuntu-latest + steps: + - name: Check tool lint status + if: ${{ needs.lint.result != 'success' && needs.flake8.result != 'skipped' }} + run: exit 1 + - name: Indicate Python script lint status + if: ${{ needs.flake8.result != 'success' && needs.flake8.result != 'skipped' }} + run: exit 1 + - name: Indicate R script lint status + if: ${{ needs.lintr.result != 'success' && needs.lintr.result != 'skipped' }} + run: exit 1 + - name: Check tool test status + if: ${{ needs.combine_outputs.result != 'success' && needs.combine_outputs.result != 'skipped' }} + run: exit 1 diff --git a/.github/workflows/slash.yaml b/.github/workflows/slash.yaml new file mode 100644 index 0000000..664d539 --- /dev/null +++ b/.github/workflows/slash.yaml @@ -0,0 +1,15 @@ +name: Slash Command Dispatch +on: + issue_comment: + types: [created] +jobs: + slashCommandDispatch: + runs-on: ubuntu-latest + steps: + - name: Slash Command Dispatch + if: github.repository_owner == 'galaxyproject' + uses: peter-evans/slash-command-dispatch@v2 + with: + token: ${{ secrets.PAT }} + commands: | + run-all-tool-tests