diff --git a/.github/workflows/ruby-test-matrix.yml b/.github/workflows/ruby-test-matrix.yml index 033f3e7..6ceafe7 100644 --- a/.github/workflows/ruby-test-matrix.yml +++ b/.github/workflows/ruby-test-matrix.yml @@ -15,10 +15,38 @@ on: required: false default: "bundle exec rspec" type: string + coverage-files: + description: >- + Comma-separated coverage report paths to upload. + Set to an empty string to disable the upload step entirely. + required: false + default: "coverage/lcov.info" + type: string + coverage-flags: + description: >- + Comma-separated Codecov flags used to group coverage metrics. + Each flag must match ^[\w\.\-]{1,45}$ (no slashes). + required: false + default: "" + type: string + coverage-fail-on-error: + description: >- + Fail the job when the Codecov upload errors. + False by default, matching the informational posture used everywhere else. + required: false + default: false + type: boolean + coverage-name: + description: Label shown for this upload in the Codecov UI. Defaults to the matrix cell. + required: false + default: "" + type: string secrets: CODECOV_TOKEN: required: false - description: Optional Codecov upload token for coverage reports + description: >- + Org-level Codecov upload token. One value works for every repository. + Omit on public repositories to fall back to tokenless upload. jobs: gemfile-paths: @@ -60,13 +88,34 @@ jobs: max_attempts: 2 timeout_minutes: 10 command: ${{ inputs.test-command }} + # Two steps so continue-on-error is a real YAML boolean. An expression + # here is unreliable: GitHub treats a quoted "false" as true, and + # fromJSON('') blows up when the boolean input is the default. - name: Upload coverage reports to Codecov + if: ${{ inputs.coverage-files != '' && !inputs.coverage-fail-on-error }} continue-on-error: true - if: ${{ hashFiles('coverage/lcov.info') != '' }} - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 + with: + token: ${{ secrets.CODECOV_TOKEN }} + slug: ${{ github.repository }} + files: ${{ inputs.coverage-files }} + flags: ${{ inputs.coverage-flags }} + name: ${{ inputs.coverage-name || format('ruby-{0}-{1}', matrix.ruby, matrix.gemfile) }} + disable_search: true + handle_no_reports_found: true + fail_ci_if_error: false + - name: Upload coverage reports to Codecov + if: ${{ inputs.coverage-files != '' && inputs.coverage-fail-on-error }} + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: token: ${{ secrets.CODECOV_TOKEN }} - files: coverage/lcov.info + slug: ${{ github.repository }} + files: ${{ inputs.coverage-files }} + flags: ${{ inputs.coverage-flags }} + name: ${{ inputs.coverage-name || format('ruby-{0}-{1}', matrix.ruby, matrix.gemfile) }} + disable_search: true + handle_no_reports_found: true + fail_ci_if_error: true build_success: if: always() diff --git a/README.md b/README.md index a019709..185a321 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Other workflows can run this workflow similar to using a Github Action jobs: tests: uses: Invoca/ruby-test-matrix-workflow/.github/workflows/ruby-test-matrix.yml@main + secrets: inherit ``` This default usage will run the rspec test suite using the following matrix strategy @@ -21,6 +22,8 @@ matrix: gemfile: // All files from the calling repo that ends with `*gemfile` ``` +`secrets: inherit` passes the org-level `CODECOV_TOKEN` into the reusable workflow. One token works for every repository; there is nothing to provision per repo. Public repositories can omit the token and fall back to tokenless upload. Fork pull requests always take that fallback, because GitHub does not pass secrets to workflows triggered by `pull_request` from a fork. + ### Available Parameters Parameters can be passed to the workflow using the usual Github Action syntax @@ -48,3 +51,33 @@ with: with: test-command: "bundle exec rake test" ``` + +## Codecov + +After tests, each matrix cell uploads coverage with `codecov/codecov-action` pinned to v7.0.0. The house convention is a single LCOV file at `coverage/lcov.info`. Copy [Invoca/escalate/spec/simplecov_helper.rb](https://github.com/Invoca/escalate/blob/master/spec/simplecov_helper.rb) (and `gem "simplecov", "~> 0.22"` plus `gem "simplecov-lcov", "~> 0.8"`) so the tests actually write that file. Without it the upload step still runs, reports that nothing was found, and the job stays green. + +These inputs are the GitHub Actions spelling of the same three concepts as the [codecov-buildkite-plugin](https://github.com/Invoca/codecov-buildkite-plugin): files, flags, and fail on error. + +* `coverage-files`: (string, optional) Comma-separated coverage report paths to upload. Set to an empty string to disable the upload step entirely. Defaults to `"coverage/lcov.info"`. + ```yaml + with: + coverage-files: "coverage/lcov.info" + ``` + +* `coverage-flags`: (string, optional) Comma-separated Codecov flags used to group coverage metrics. Each flag must match `^[\w\.\-]{1,45}$` (no slashes). Defaults to `""`. + ```yaml + with: + coverage-flags: "ruby" + ``` + +* `coverage-fail-on-error`: (boolean, optional) Fail the job when the Codecov upload errors. False by default, matching the informational posture used everywhere else. Pass `true` to make a failed upload fail the job. + ```yaml + with: + coverage-fail-on-error: true + ``` + +* `coverage-name`: (string, optional) Label shown for this upload in the Codecov UI. Defaults to the matrix cell (`ruby--`). + ```yaml + with: + coverage-name: "unit" + ```