diff --git a/.flake8_requirements b/.flake8_requirements new file mode 100644 index 0000000..90225d0 --- /dev/null +++ b/.flake8_requirements @@ -0,0 +1,2 @@ +flake8 +flake8-import-order diff --git a/.github/workflows/tools.yaml b/.github/workflows/tools.yaml index 7a34ded..fe5552b 100644 --- a/.github/workflows/tools.yaml +++ b/.github/workflows/tools.yaml @@ -19,7 +19,7 @@ jobs: chunk-list: ${{ steps.discover.outputs.chunk-list }} strategy: matrix: - python-version: [3.7] + python-version: ['3.7'] steps: - name: Print github context properties run: | @@ -85,198 +85,90 @@ jobs: setup-ci-tools: name: Setup as in CI for tools + if: ${{ github.repository_owner == 'galaxyproject' }} + uses: ./.github/workflows/wf_setup.yaml + with: + # default-galaxy-fork: galaxyproject + # default-galaxy-branch: release_22.05 + max-chunks: 40 + github-event-name-override: 'schedule' + secrets: + PAT: ${{ secrets.PAT }} + + check-setup-ci-tools: + name: Check setup + needs: setup-ci-tools 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: Determine latest commit in the Galaxy repo - id: get-galaxy-sha - run: echo "galaxy-head-sha=$(git ls-remote https://github.com/${{ env.GALAXY_FORK }}/galaxy refs/heads/${{ env.GALAXY_BRANCH }} | cut -f1)" >> $GITHUB_OUTPUT - - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Cache .cache/pip - uses: actions/cache@v3 - 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@v3 - with: - fetch-depth: 1 - - name: Artificially exclude workflows (because ci_find_repos discovers tool and workflow repos) - run: echo 'test/workflows/' > .tt_skip - - name: Fake a Planemo run to update cache and determine commit range, repositories, and chunks - uses: ./ - id: discover - env: - GITHUB_EVENT_NAME: schedule - with: - create-cache: true - galaxy-fork: ${{ env.GALAXY_FORK }} - galaxy-branch: ${{ env.GALAXY_BRANCH }} - max-chunks: ${{ env.MAX_CHUNKS }} - python-version: ${{ matrix.python-version }} - github-event-name-override: 'schedule' - name: Check for empty commit range - run: if [ -n "${{ steps.discover.outputs.commit-range }}" ]; then exit 1; fi + run: if [ -n "${{ needs.setup-ci-tools.outputs.commit-range }}" ]; then exit 1; fi # note: ci_find_repos will find all tools and workflows - name: Check that all tools an workflows are in the repository list run: | - if ! grep -q "tool1" <<<$(echo "${{ steps.discover.outputs.repository-list }}"); then echo "tool1 must be in the repo list"; exit 1; fi - if ! grep -q "tool2" <<<$(echo "${{ steps.discover.outputs.repository-list }}"); then echo "tool2 must be in the repo list"; exit 1; fi - if grep -q "example3" <<<$(echo "${{ steps.discover.outputs.repository-list }}"); then echo "example3 must not be in the repo list"; exit 1; fi - if grep -q "example4" <<<$(echo "${{ steps.discover.outputs.repository-list }}"); then echo "example4 must not be in the repo list"; exit 1; fi + if ! grep -q "tool1" <<<$(echo "${{ needs.setup-ci-tools.outputs.repository-list }}"); then echo "tool1 must be in the repo list"; exit 1; fi + if ! grep -q "tool2" <<<$(echo "${{ needs.setup-ci-tools.outputs.repository-list }}"); then echo "tool2 must be in the repo list"; exit 1; fi + if grep -q "example3" <<<$(echo "${{ needs.setup-ci-tools.outputs.repository-list }}"); then echo "example3 must not be in the repo list"; exit 1; fi + if grep -q "example4" <<<$(echo "${{ needs.setup-ci-tools.outputs.repository-list }}"); then echo "example4 must not be in the repo list"; exit 1; fi # note: ci_find_tools will find onlytools - name: Check that all tools are in the tool list run: | - if ! grep -q "tool1.xml" <<<$(echo "${{ steps.discover.outputs.tool-list }}"); then echo "tool1.xml must be in the repo list"; exit 1; fi - if ! grep -q "tool2.xml" <<<$(echo "${{ steps.discover.outputs.tool-list }}"); then echo "tool2.xml must be in the repo list"; exit 1; fi + if ! grep -q "tool1.xml" <<<$(echo "${{ needs.setup-ci-tools.outputs.tool-list }}"); then echo "tool1.xml must be in the repo list"; exit 1; fi + if ! grep -q "tool2.xml" <<<$(echo "${{ needs.setup-ci-tools.outputs.tool-list }}"); then echo "tool2.xml must be in the repo list"; exit 1; fi # chunk-count will only consider tools/workflows depending on the workflow input to the action - name: Check that the number of chunks is three, i.e. the number of tools - run: if [ "${{ steps.discover.outputs.chunk-count }}" != "3" ]; then exit 1; fi + run: if [ "${{ needs.setup-ci-tools.outputs.chunk-count }}" != "3" ]; then exit 1; fi lint: - name: Test linting of tools - needs: [setup-ci-tools] + name: Lint + needs: setup-ci-tools + uses: ./.github/workflows/wf_lint.yaml + with: + repository-list: ${{ needs.setup-ci-tools.outputs.repository-list }} + tool-list: ${{ needs.setup-ci-tools.outputs.tool-list }} + galaxy-head-sha: ${{ needs.setup-ci-tools.outputs.galaxy-head-sha }} + commit-range: ${{ needs.setup-ci-tools.outputs.commit-range }} + planemo-version: ${{ needs.setup-ci-tools.outputs.planemo-version }} + fail-level: error + + check-lint: + name: Check linting results + needs: lint runs-on: ubuntu-latest - strategy: - matrix: - python-version: [3.7] - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 1 - - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Cache .cache/pip - uses: actions/cache@v3 - id: cache-pip - with: - path: ~/.cache/pip - key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup-ci-tools.outputs.galaxy-head-sha }} - - name: Install wheel - run: pip install wheel - - name: Planemo lint tools - uses: ./ + steps: + - uses: actions/download-artifact@v3 with: - mode: lint - report-level: all - fail-level: error - repository-list: ${{ needs.setup-ci-tools.outputs.repository-list }} - tool-list: ${{ needs.setup-ci-tools.outputs.tool-list }} - additional-planemo-options: --report_level all - continue-on-error: true + path: lint_report.txt + # TODO check result of lint job (ie make sure it failed) - name: check if all test tools were linted run: | grep tool1 lint_report.txt grep tool2 lint_report.txt grep "ERROR: Error 'HTTPConnectionPool" lint_report.txt grep "Applying linter tests... CHECK" lint_report.txt + test-tools: - name: Test testing of tools - needs: [setup-ci-tools] - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - chunk: ${{ fromJson(needs.setup-ci-tools.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@v3 - with: - fetch-depth: 1 - - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Cache .cache/pip - uses: actions/cache@v3 - id: cache-pip - with: - path: ~/.cache/pip - key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup-ci-tools.outputs.galaxy-head-sha }} - - name: Get number of CPU cores - uses: SimenB/github-actions-cpu-cores@v1 - id: cpu-cores - - name: Planemo test tools - uses: ./ - id: test-tools - with: - mode: test - repository-list: ${{ needs.setup-ci-tools.outputs.repository-list }} - galaxy-fork: ${{ env.GALAXY_FORK }} - galaxy-branch: ${{ env.GALAXY_BRANCH }} - chunk: ${{ matrix.chunk }} - chunk-count: ${{ needs.setup-ci-tools.outputs.chunk-count }} - additional-planemo-options: --simultaneous_uploads --check_uploads_ok - galaxy-slots: ${{ steps.cpu-cores.outputs.count }} - - uses: actions/upload-artifact@v3 - with: - name: 'Tool test output ${{ matrix.chunk }}' - path: upload + name: Test tools + needs: setup-ci-tools + uses: ./.github/workflows/wf_test.yaml + with: + galaxy-fork: ${{ needs.setup-ci-tools.outputs.galaxy-fork }} + galaxy-branch: ${{ needs.setup-ci-tools.outputs.galaxy-branch }} + planemo-version: ${{ needs.setup-ci-tools.outputs.planemo-version }} + repository-list: ${{ needs.setup-ci-tools.outputs.repository-list }} + chunk-count: ${{ needs.setup-ci-tools.outputs.chunk-count }} + chunk-list: ${{ needs.setup-ci-tools.outputs.chunk-list }} + galaxy-head-sha: ${{ needs.setup-ci-tools.outputs.galaxy-head-sha }} + # set these values if you want to use different values than the IUC defaults + # test-timeout: 900 - combine_outputs: - name: Test combining 'chunked' test results + check-test: + name: Check testing results needs: [setup-ci-tools, test-tools] - strategy: - matrix: - python-version: [3.7] - # This job runs on Linux runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 1 - - uses: actions/download-artifact@v3 - with: - path: artifacts - - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Cache .cache/pip - uses: actions/cache@v3 - id: cache-pip - with: - path: ~/.cache/pip - key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ needs.setup-ci-tools.outputs.galaxy-head-sha }} - - name: Combine outputs - uses: ./ - id: combine - with: - mode: combine - html-report: true - name: Check statistics - run: if ! grep -q "3\s\+success" <<<$(echo ${{ steps.combine.outputs.statistics }}); then echo "wrong statistics"; exit 1; fi + run: if ! grep -q "3\s\+success" <<<$(echo ${{ needs.test-tools.outputs.statistics }}); then echo "wrong statistics"; exit 1; fi - uses: actions/upload-artifact@v3 with: name: 'All tool test results' path: upload - - name: Check outputs - uses: ./ - id: check - with: - mode: check diff --git a/.github/workflows/wf_deploy.yaml b/.github/workflows/wf_deploy.yaml new file mode 100644 index 0000000..fb4ce76 --- /dev/null +++ b/.github/workflows/wf_deploy.yaml @@ -0,0 +1,89 @@ +name: Deploy Tools +on: + workflow_call: + inputs: + galaxy-head-sha: + description: 'hash of the latest commit in the Galaxy repo' + required: true + type: string + repository-list: + description: 'list of repositories to deploy' + required: true + type: string + python-version-list: + description: 'Python versions (stringified JSON array)' + default: "[\"3.7\"]" + required: false + type: string + planemo-version: + description: 'Planemo version to use' + default: "planemo" + required: false + type: string + secrets: + TTS_API_KEY: + required: true + TS_API_KEY: + required: true + +jobs: + # deploy the tools to the toolsheds (first TTS for testing) + deploy: + name: Deploy + if: ${{ (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' ) }} + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ${{ fromJson(inputs.python-version-list) }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 1 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v3 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ inputs.galaxy-head-sha }}_planemo_${{ steps.get-galaxy-sha.outputs.planemo-version }} + - name: Deploy on testtoolshed + uses: ./ + with: + mode: deploy + repository-list: ${{ inputs.repository-list }} + shed-target: testtoolshed + shed-key: ${{ secrets.TTS_API_KEY }} + planemo-version: ${{ inputs.planemo-version }} + continue-on-error: true + - name: Deploy on toolshed + uses: ./ + with: + mode: deploy + repository-list: ${{ inputs.repository-list }} + shed-target: toolshed + shed-key: ${{ secrets.TS_API_KEY }} + planemo-version: ${{ inputs.planemo-version }} + + deploy-report: + name: Report deploy status + needs: [deploy] + if: ${{ always() && needs.deploy.result != 'success' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main' ) }} + runs-on: ubuntu-latest + steps: + # report to the PR if deployment failed + - name: Get PR object + uses: 8BitJonny/gh-get-current-pr@2.2.0 + id: getpr + with: + sha: ${{ github.event.after }} + - name: Create comment + uses: peter-evans/create-or-update-comment@v2 + with: + token: ${{ secrets.PAT }} + issue-number: ${{ steps.getpr.outputs.number }} + body: | + Attention: deployment ${{ needs.deploy.result }}! + + https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} \ No newline at end of file diff --git a/.github/workflows/wf_lint.yaml b/.github/workflows/wf_lint.yaml new file mode 100644 index 0000000..5bca14e --- /dev/null +++ b/.github/workflows/wf_lint.yaml @@ -0,0 +1,234 @@ +name: Lint +on: + workflow_call: + inputs: + repository-list: + description: 'list of repositories to lint' + default: '' + required: false + type: string + tool-list: + description: 'list of tools to lint' + default: '' + required: false + type: string + report-level: + description: 'Tool lint report level' + default: 'all' + required: false + type: string + fail-level: + description: 'Tool lint fail level' + default: 'warn' + required: false + type: string + galaxy-head-sha: + description: 'hash of the latest commit in the Galaxy repo' + required: true + type: string + commit-range: + description: 'commit range to test' + default: '' + required: false + type: string + max-file-size: + description: 'maximum file size' + default: "1M" + required: false + type: string + python-version-list: + description: 'stringified JSON array of Python versions' + default: "[\"3.7\"]" + required: false + type: string + r-version-list: + description: 'stringified JSON array of R versions' + default: "[\"release\"]" + required: false + type: string + os-version-list: + description: 'stringified JSON array of OS versions' + default: "[\"ubuntu-20.04\"]" + required: false + type: string + planemo-version: + description: 'Planemo version to use' + default: "planemo" + required: false + type: string + outputs: + result: + description: "Result of the lint jobs" + value: ${{ jobs.lint-success.result }} + +jobs: + lint: + name: Tools + if: ${{ inputs.repository-list != '' || inputs.tool-list != '' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ${{ fromJson(inputs.python-version-list) }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 1 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v3 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ inputs.galaxy-head-sha }}_planemo_${{ steps.get-galaxy-sha.outputs.planemo-version }} + - name: Planemo lint + uses: ./ + id: lint + with: + mode: lint + report-level: ${{ inputs.report-level }} + fail-level: ${{ inputs.fail-level }} + repository-list: ${{ inputs.repository-list }} + tool-list: ${{ inputs.tool-list }} + planemo-version: ${{ inputs.planemo-version }} + - uses: actions/upload-artifact@v3 + if: ${{ failure() }} + with: + name: 'Tool linting output' + path: lint_report.txt + + flake8: + name: Python scripts + if: ${{ inputs.repository-list != '' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ${{ fromJson(inputs.python-version-list) }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 1 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v3 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ inputs.galaxy-head-sha }}_planemo_${{ steps.get-galaxy-sha.outputs.planemo-version }} + - name: Install flake8 + run: pip install -r .flake8_requirements + - name: Flake8 + run: echo '${{ inputs.repository-list }}' | xargs -d '\n' flake8 --output-file pylint_report.txt --tee + - uses: actions/upload-artifact@v3 + if: ${{ failure() }} + with: + name: 'Python linting output' + path: pylint_report.txt + + lintr: + name: R scripts + if: ${{ inputs.repository-list != '' }} + strategy: + matrix: + os: ${{ fromJson(inputs.os-version-list) }} + r-version: ${{ fromJson(inputs.r-version-list) }} + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 1 + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.r-version }} + - name: Cache R packages + uses: actions/cache@v3 + 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 '${{ inputs.repository-list }}' > repository_list.txt + - name: lintr + run: | + library(lintr) + linters <- 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, paste("(", l$line, ")")), stderr()) + write(paste(paste(rel_path, l$line_number, l$column_number, sep=":"), l$message, paste("(", l$line, ")")), "rlint_report.txt", append=TRUE) + } + } + } + quit(status = status) + shell: Rscript {0} + - uses: actions/upload-artifact@v3 + if: ${{ failure() }} + with: + name: 'R linting output' + path: rlint_report.txt + + file_sizes: + name: Check file sizes + if: ${{ github.event_name == 'pull_request' && inputs.repository-list != '' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Check file sizes + run: | + touch file_size_report.txt + git diff --diff-filter=d --name-only ${{ inputs.commit-range }} > git.diff + while read line; do + find "$line" -type f -size +${{ inputs.max-file-size }} >> file_size_report.txt + done < git.diff + if [[ -s file_size_report.txt ]]; then + echo "Files larger than ${{ inputs.max-file-size }} found" + cat file_size_report.txt + exit 1 + fi + - uses: actions/upload-artifact@v3 + if: ${{ failure() }} + with: + name: 'File size report' + path: file_size_report.txt + + lint-success: + name: Determine lint success + needs: [lint, flake8, lintr, file_sizes] + 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: Indicate file size check status + if: ${{ needs.file_sizes.result != 'success' && needs.file_sizes.result != 'skipped' }} + run: exit 1 diff --git a/.github/workflows/wf_setup.yaml b/.github/workflows/wf_setup.yaml new file mode 100644 index 0000000..bba67ae --- /dev/null +++ b/.github/workflows/wf_setup.yaml @@ -0,0 +1,181 @@ +name: Setup tool tests +on: + workflow_call: + inputs: + default-galaxy-fork: + description: 'Default Galaxy fork to use' + default: 'galaxyproject' + required: false + type: string + default-galaxy-branch: + description: 'Default Galaxy branch to use' + default: 'release_22.05' + required: false + type: string + default-planemo-version: + description: 'Default planemo version to use' + default: 'planemo' + required: false + type: string + max-chunks: + description: 'maximum number of chunks to use' + required: true + type: number + fetch-depth: + description: 'Number of commits to fetch. 0 indicates all history for all branches and tags' + default: 1 + required: false + type: number + python-version-list: + description: 'Python versions (stringified JSON array)' + default: "[\"3.7\"]" + required: false + type: string + ## supposed to be used in internal testing only + github-event-name-override: + description: 'ONLY FOR TESTING: override GITHUB_EVENT_NAME' + default: '' + required: false + type: string + github-ref-override: + description: 'ONLY FOR TESTING: override GITHUB_REF' + default: '' + required: false + type: string + secrets: + PAT: + required: false + outputs: + galaxy-head-sha: + description: "hash of the latest commit in the Galaxy repo" + value: ${{ jobs.setup.outputs.galaxy-head-sha }} + repository-list: + description: "list of repositories to test" + value: ${{ jobs.setup.outputs.repository-list }} + tool-list: + description: "list of tools to test" + value: ${{ jobs.setup.outputs.tool-list }} + chunk-count: + description: "number of chunks" + value: ${{ jobs.setup.outputs.chunk-count }} + chunk-list: + description: "list of chunks (stringified JSON array)" + value: ${{ jobs.setup.outputs.chunk-list }} + commit-range: + description: "commit range to test" + value: ${{ jobs.setup.outputs.commit-range }} + galaxy-fork: + description: "The determined galaxy fork to use" + value: ${{ jobs.fork-branch.outputs.galaxy-fork }} + galaxy-branch: + description: "The determined galaxy branch to use" + value: ${{ jobs.fork-branch.outputs.galaxy-branch }} + planemo-version: + description: "The determined planemo version to use" + value: ${{ jobs.fork-branch.outputs.planemo-version }} +jobs: + fork-branch: + name: Determine Galaxy fork and branch to use + runs-on: ubuntu-latest + outputs: + galaxy-fork: ${{ steps.get-fork-branch.outputs.fork }} + galaxy-branch: ${{ steps.get-fork-branch.outputs.branch }} + planemo-version: ${{ steps.get-fork-branch.outputs.planemo-version }} + steps: + - name: Add reaction + if: ${{ github.event.client_payload.slash_command.command == 'run-all-tool-tests' }} + uses: peter-evans/create-or-update-comment@v2 + 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: | + SLASH_FORK="${{ github.event.client_payload.slash_command.args.named.fork }}" + DEFAULT_FORK="${{ inputs.default-galaxy-fork }}" + echo "fork=${SLASH_FORK:-$DEFAULT_FORK}" >> $GITHUB_OUTPUT + SLASH_BRANCH="${{ github.event.client_payload.slash_command.args.named.branch }}" + DEFAULT_BRANCH="${{ inputs.default-galaxy-branch }}" + echo "branch=${SLASH_BRANCH:-$DEFAULT_BRANCH}" >> $GITHUB_OUTPUT + SLASH_PLANEMO="${{ github.event.client_payload.slash_command.args.named.planemo-version }}" + DEFAULT_PLANEMO="${{ inputs.default-planemo-version }}" + echo "planemo-version=${SLASH_PLANEMO:-$DEFAULT_PLANEMO}" >> $GITHUB_OUTPUT + - name: Print used Galaxy fork and branch and planemo version + run: | + echo 'fork: ${{ steps.get-fork-branch.outputs.fork }}' + echo 'branch: ${{ steps.get-fork-branch.outputs.branch }}' + echo 'planemo-version: ${{ steps.get-fork-branch.outputs.planemo-version }}' + setup: + name: Setup cache and determine changed repositories + needs: fork-branch + 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 }} + commit-range: ${{ steps.discover.outputs.commit-range }} + strategy: + matrix: + python-version: ${{ fromJson(inputs.python-version-list) }} + 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 "galaxy-head-sha=$(git ls-remote https://github.com/${{ needs.fork-branch.outputs.galaxy-fork }}/galaxy refs/heads/${{ needs.fork-branch.outputs.galaxy-branch }} | cut -f1)" >> $GITHUB_OUTPUT + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v3 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ steps.get-galaxy-sha.outputs.galaxy-head-sha }}_planemo_${{ steps.get-galaxy-sha.outputs.planemo-version }} + - name: Cache .planemo + uses: actions/cache@v3 + id: cache-planemo + with: + path: ~/.planemo + key: planemo_cache_py_${{ matrix.python-version }}_gxy_${{ steps.get-galaxy-sha.outputs.galaxy-head-sha }}_planemo_${{ steps.get-galaxy-sha.outputs.planemo-version }} + # 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@v3 + with: + fetch-depth: ${{ inputs.fetch-depth }} + - name: Fake a Planemo run to update cache and determine commit range, repositories, and chunks + uses: ./ + id: discover + with: + create-cache: ${{ steps.cache-pip.outputs.cache-hit != 'true' || steps.cache-planemo.outputs.cache-hit != 'true' }} + galaxy-fork: ${{ needs.fork-branch.outputs.galaxy-fork }} + galaxy-branch: ${{ needs.fork-branch.outputs.galaxy-branch }} + max-chunks: ${{ inputs.max-chunks }} + python-version: ${{ matrix.python-version }} + planemo-version: ${{ needs.fork-branch.outputs.planemo-version }} + github-event-name-override: ${{ inputs.github-event-name-override }} + github-ref-override: ${{ inputs.github-ref-override }} + - 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 }})' \ No newline at end of file diff --git a/.github/workflows/wf_test.yaml b/.github/workflows/wf_test.yaml new file mode 100644 index 0000000..6d6e6ba --- /dev/null +++ b/.github/workflows/wf_test.yaml @@ -0,0 +1,198 @@ +name: Test tools +on: + workflow_call: + inputs: + python-version-list: + description: 'Python versions (stringified JSON array)' + default: "[\"3.7\"]" + required: false + type: string + chunk-count: + description: 'number of chunks' + required: true + type: string + chunk-list: + description: 'list of chunks (stringified JSON array)' + required: true + type: string + repository-list: + description: 'list of repositories to test' + required: true + type: string + galaxy-head-sha: + description: 'hash of the latest commit in the Galaxy repo' + required: true + type: string + galaxy-fork: + description: 'Galaxy fork to use' + required: true + type: string + galaxy-branch: + description: 'Galaxy branch to use' + required: true + type: string + cache-planemo: + description: 'cache the .planemo directory' + default: true + required: false + type: boolean + test-timeout: + description: 'Timeout in seconds per test' + default: 900 + required: false + type: number + planemo-version: + description: 'Planemo version to use' + default: "planemo" + required: false + type: string + secrets: + PAT: + required: false + outputs: + result: + description: "Result of the testing" + value: ${{ jobs.test-success.result }} + statistics: + description: "Statistics of the test results" + value: "${{ jobs.combine_outputs.outputs.statistics }}" +jobs: + # Planemo test the changed repositories, each chunk creates an artifact + # containing HTML and JSON reports for the executed tests + test: + name: Test tools + if: ${{ inputs.repository-list != '' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + chunk: ${{ fromJson(inputs.chunk-list) }} + python-version: ${{ fromJson(inputs.python-version-list) }} + services: + postgres: + image: postgres:11 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: postgres + ports: + - 5432:5432 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 1 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v3 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ inputs.galaxy-head-sha }}_planemo_${{ steps.get-galaxy-sha.outputs.planemo-version }} + - name: Cache .planemo + if: ${{ inputs.cache-planemo }} + uses: actions/cache@v3 + id: cache-planemo + with: + path: ~/.planemo + key: planemo_cache_py_${{ matrix.python-version }}_gxy_${{ inputs.galaxy-head-sha }}_planemo_${{ steps.get-galaxy-sha.outputs.planemo-version }} + - name: Get number of CPU cores + uses: SimenB/github-actions-cpu-cores@v1 + id: cpu-cores + - name: Clean dotnet folder for space + run: rm -Rf /usr/share/dotnet + - name: Planemo test + uses: ./ + id: test + with: + mode: test + repository-list: ${{ inputs.repository-list }} + galaxy-fork: ${{ inputs.galaxy-fork }} + galaxy-branch: ${{ inputs.galaxy-branch }} + chunk: ${{ matrix.chunk }} + chunk-count: ${{ inputs.chunk-count }} + galaxy-slots: ${{ steps.cpu-cores.outputs.count }} + # Limit each test to 15 minutes + test_timeout: ${{ inputs.test-timeout }} + planemo-version: ${{ inputs.planemo-version }} + - uses: actions/upload-artifact@v3 + 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: test + runs-on: ubuntu-latest + outputs: + galaxy-fork: ${{ steps.combine.outputs.statistics }} + strategy: + matrix: + python-version: ${{ fromJson(inputs.python-version-list) }} + steps: + - uses: actions/download-artifact@v3 + with: + path: artifacts + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Cache .cache/pip + uses: actions/cache@v3 + id: cache-pip + with: + path: ~/.cache/pip + key: pip_cache_py_${{ matrix.python-version }}_gxy_${{ inputs.galaxy-head-sha }}_planemo_${{ steps.get-galaxy-sha.outputs.planemo-version }} + - name: Combine outputs + uses: ./ + id: combine + with: + mode: combine + planemo-version: ${{ inputs.planemo-version }} + html-report: true + - uses: actions/upload-artifact@v3 + 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 "run-url=https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" >> $GITHUB_OUTPUT + - name: Create comment + if: ${{ github.event.client_payload.slash_command.command == 'run-all-tool-tests' }} + uses: peter-evans/create-or-update-comment@v2 + 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: Print statistics + run: | + echo "${{ steps.combine.outputs.statistics }}" + - name: Check outputs + uses: ./ + id: check + with: + mode: check + + test-success: + name: Determine test success + needs: [combine_outputs] + if: ${{ always() && github.ref != 'refs/heads/master' && github.ref != 'refs/heads/main' }} + runs-on: ubuntu-latest + steps: + - name: Check tool test status + if: ${{ needs.combine_outputs.result != 'success' && needs.combine_outputs.result != 'skipped' }} + run: exit 1 diff --git a/.github/workflows/workflows.yaml b/.github/workflows/workflows.yaml index bc506be..635a75a 100644 --- a/.github/workflows/workflows.yaml +++ b/.github/workflows/workflows.yaml @@ -117,8 +117,6 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: 1 - - name: Artificially exclude tools (because ci_find_repos discovers tool and workflow repos) - run: echo 'test/tools/' > .tt_skip - name: Fake a Planemo run to update cache and determine commit range, repositories, and chunks uses: ./ id: discover diff --git a/.tt_skip b/.tt_skip new file mode 100644 index 0000000..e1b4e62 --- /dev/null +++ b/.tt_skip @@ -0,0 +1 @@ +test/workflows/ \ No newline at end of file diff --git a/.wt_skip b/.wt_skip new file mode 100644 index 0000000..300b835 --- /dev/null +++ b/.wt_skip @@ -0,0 +1 @@ +test/tools/ \ No newline at end of file diff --git a/planemo_ci_actions.sh b/planemo_ci_actions.sh index 3370892..986779b 100755 --- a/planemo_ci_actions.sh +++ b/planemo_ci_actions.sh @@ -19,12 +19,18 @@ fi GITHUB_EVENT_NAME=${GITHUB_EVENT_NAME_OVERRIDE:-$GITHUB_EVENT_NAME} GITHUB_REF=${GITHUB_REF_OVERRIDE:-$GITHUB_REF} +if [ "$WORKFLOWS" == "true" ]; then + SKIP_FILE=".wt_skip" +else + SKIP_FILE=".tt_skip" +fi + # setup mode # - get commit range (for push and pull_request events) .. # not set for sheduled and repository_dispatch events # - get list of relevant tools and repositories # - tools/repos in the commit range (if set) -# - tools/repos not listed in .tt_skip or contained in +# - tools/repos not listed in .tt_skip (resp .wt_skip) or contained in # `packages/` or `deprecated/` # - determine chunk count as linear function of the number # of tools (limited by MAX_CHUNK) @@ -66,13 +72,13 @@ if [ "$REPOSITORIES" == "" ] && [ "$MODE" == "setup" ]; then PLANEMO_COMMIT_RANGE=("--changed_in_commit_range" "$COMMIT_RANGE") fi - touch .tt_skip - planemo ci_find_repos "${PLANEMO_COMMIT_RANGE[@]}" --exclude packages --exclude deprecated --exclude_from .tt_skip --output repository_list.txt + touch "$SKIP_FILE" + planemo ci_find_repos "${PLANEMO_COMMIT_RANGE[@]}" --exclude packages --exclude deprecated --exclude_from "$SKIP_FILE" --output repository_list.txt REPOSITORIES=$(cat repository_list.txt) touch tool_list.txt if [ "$WORKFLOWS" != "true" ]; then - planemo ci_find_tools "${PLANEMO_COMMIT_RANGE[@]}" --exclude packages --exclude deprecated --exclude_from .tt_skip --output tool_list.txt + planemo ci_find_tools "${PLANEMO_COMMIT_RANGE[@]}" --exclude packages --exclude deprecated --exclude_from "$SKIP_FILE" --output tool_list.txt TOOLS=$(cat tool_list.txt) fi diff --git a/test/tools/galaxy_slots/.shed.yml b/test/tools/galaxy_slots/.shed.yml index 7ff5cd8..a6bd43a 100644 --- a/test/tools/galaxy_slots/.shed.yml +++ b/test/tools/galaxy_slots/.shed.yml @@ -1,4 +1,4 @@ -categories: [Sequence Analysis] +categories: [Testing] description: test setting GALAXY_SLOTS name: galaxy_slots owner: adent