├── .deepsource.toml ├── .editorconfig ├── .github └── CODEOWNERS ├── Dockerfile ├── LICENSE ├── README.md ├── action.yml └── main.py /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[analyzers]] 4 | name = 'python' 5 | enabled = true 6 | 7 | [analyzers.meta] 8 | max_line_length = 100 9 | skip_doc_coverage = ["module", "magic", "class"] 10 | runtime_version = '3.x.x' 11 | 12 | [[analyzers]] 13 | name = "docker" 14 | enabled = true 15 | 16 | [[transformers]] 17 | name = 'black' 18 | enabled = true 19 | 20 | [[analyzers]] 21 | name = "secrets" 22 | enabled = true 23 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.py] 12 | indent_style = space 13 | indent_size = 4 14 | 15 | [Makefile] 16 | indent_style = tab 17 | 18 | [*.md] 19 | trim_trailing_whitespace = false 20 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * srijan@deepsource.io -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8.7-slim-buster 2 | ENV PYTHONPATH /app 3 | ENV PYTHONUNBUFFERED 1 4 | ENV PYTHONDONTWRITEBYTECODE 1 5 | 6 | RUN groupadd --gid 5000 main \ 7 | && useradd --home-dir /home/main --create-home --uid 5000 \ 8 | --gid 5000 --shell /bin/sh --skel /dev/null main 9 | 10 | COPY . /app 11 | WORKDIR /app 12 | 13 | # install curl; skipcq: DOK-DL3008 14 | RUN apt-get update && apt-get install --no-install-recommends -y curl git && apt-get clean && rm -rf /var/lib/apt/lists/* 15 | SHELL ["/bin/bash", "-o", "pipefail", "-c"] 16 | 17 | # download the DeepSource CLI binary 18 | RUN curl https://deepsource.io/cli | bash 19 | RUN ["chmod", "777", "/app/main.py"] 20 | 21 | USER main 22 | 23 | CMD ["/app/main.py"] 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 DeepSource Corp. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 |

6 | Docs | 7 | Get Started | 8 | Discuss 9 |

10 | 11 |

12 | The Code Health Platform 13 |

14 | 15 |

16 | 17 | --- 18 | 19 | GitHub Action that enables you to upload your test coverage data to DeepSource easily. You must have the [Test Coverage](https://docs.deepsource.com/docs/analyzers-test-coverage) analyzer enabled on your repository for reporting to work. 20 | 21 | If you're not using DeepSource yet, [get started for free](https://deepsource.com/). 22 | 23 | ## Usage 24 | 25 | This Action assumes that the coverage file has already been generated after the tests have run. To integrate it in your workflow, define a step which refers to this Action in your `workflow.yml` file. We recommend that you use `@master` as the ref. 26 | 27 | Ensure that you have added the `DEEPSOURCE_DSN` secret in your GitHub repository. It is available under **Settings → Code Coverage** of the repository page on DeepSource. 28 | 29 | ```yaml 30 | steps: 31 | - name: Report test coverage to DeepSource 32 | uses: deepsourcelabs/test-coverage-action@master 33 | with: 34 | key: python 35 | coverage-file: coverage.xml 36 | dsn: ${{ secrets.DEEPSOURCE_DSN }} 37 | ``` 38 | 39 | The possible inputs to this action are: 40 | 41 | * `key` (string, **required**): Programming language shortcode for which coverage is reported. e.g. `python`, `go`, `javascript`. 42 | See [the docs](https://docs.deepsource.com/docs/analyzers-test-coverage#reporting-coverage-artifact-using-the-cli) for the current list of allowed values. 43 | * `coverage-file` (string, **required**): Path to the coverage data file. e. g. `coverage.xml` 44 | * `dsn` (string, **required**): DeepSource DSN of this repository. 45 | * `fail-ci-on-error` (boolean): Should the CI build fail if there is an error while uploading the report to DeepSource? Allowed values are: `true`, `false`. This is set to `false` by default. 46 | 47 | ## License 48 | 49 | This project is released under the [MIT License](LICENSE). 50 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'DeepSource Test Coverage Action' 2 | description: 'GitHub Action that uploads test coverage reports to DeepSource for the Test Coverage analyzer.' 3 | author: 'Sanket Saurav ' 4 | inputs: 5 | key: 6 | description: 'Programming language shortcode for which coverage is reported. Allowed values are — python, go, javascript, ruby, java, kotlin, scala, php, csharp, cxx, rust, swift' 7 | required: true 8 | coverage-file: 9 | description: 'Path to the coverage data file. e.g. ./coverage.xml' 10 | required: true 11 | dsn: 12 | description: 'DeepSource DSN of this repository. It is available under Settings → Reporting tab of the repository page on DeepSource.' 13 | required: true 14 | fail-ci-on-error: 15 | description: 'Should the CI build fail if there is an error while uploading the report to DeepSource? Allowed values are — true, false' 16 | default: false 17 | commit-sha: 18 | description: 'HEAD commit for which the Test Coverage report is being sent' 19 | required: false 20 | default: ${{ github.event.pull_request.head.sha }} 21 | branding: 22 | color: 'green' 23 | icon: 'umbrella' 24 | runs: 25 | using: 'docker' 26 | image: 'Dockerfile' 27 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import os 4 | import subprocess # skipcq: BAN-B404 5 | import sys 6 | 7 | # input for the actions are converted to names of a specific format by GitHub 8 | INPUT_KEYS_MAP = { 9 | "key": "INPUT_KEY", 10 | "coverage_file": "INPUT_COVERAGE-FILE", 11 | "dsn": "INPUT_DSN", 12 | "fail_ci_on_error": "INPUT_FAIL-CI-ON-ERROR", 13 | "commit_sha": "INPUT_COMMIT-SHA", 14 | } 15 | 16 | DEEPSOURCE_CLI_PATH = "/app/bin/deepsource" 17 | 18 | DEEPSOURCE_TEST_COVERAGE_ANALYZER_SHORTCODE = "test-coverage" 19 | 20 | GITHUB_WORKSPACE_PATH = os.environ.get("GITHUB_WORKSPACE") 21 | 22 | 23 | def main() -> None: 24 | """ 25 | Get the metadata required for invoking DeepSource CLI from the environment 26 | and invoke the CLI to report the test coverage. 27 | Optionally, fail with a non-zero exit code if the user has configured so. 28 | """ 29 | 30 | input_data = {key: os.getenv(value) for key, value in INPUT_KEYS_MAP.items()} 31 | commit_sha = input_data["commit_sha"] 32 | 33 | # Case: When user hasn't set the commit sha 34 | # or, when this action is run on a non-pull request event, the default value is going to 35 | # be an empty string. 36 | # in such case, fetch commit sha from the `GITHUB_SHA` environment variable. 37 | # Doing this is the best way to go because of the following reasons: 38 | # 1. we don't have to run any git commands to fetch the commit sha, 39 | # making the action work all the time 40 | # 2. the default being set to PR's head sha will take care of merge commit. 41 | # In all other cases, GITHUB_SHA would be accurate. 42 | # 3. GITHUB_SHA is always set, so we don't have to worry about it being empty. 43 | if not commit_sha: 44 | commit_sha = os.getenv("GITHUB_SHA") 45 | 46 | command = [ 47 | DEEPSOURCE_CLI_PATH, 48 | "report", 49 | "--analyzer", 50 | DEEPSOURCE_TEST_COVERAGE_ANALYZER_SHORTCODE, 51 | "--key", 52 | input_data["key"], 53 | "--value-file", 54 | input_data["coverage_file"], 55 | ] 56 | 57 | # change the current working directory to the GitHub repository's context 58 | os.chdir(GITHUB_WORKSPACE_PATH) 59 | 60 | # skipcq: BAN-B603, PYL-W1510 61 | process = subprocess.run( 62 | command, 63 | env=dict( 64 | os.environ, 65 | DEEPSOURCE_DSN=input_data["dsn"], 66 | GHA_HEAD_COMMIT_SHA=commit_sha, 67 | ), 68 | capture_output=True, 69 | ) 70 | 71 | if process.returncode != 0: 72 | if input_data["fail_ci_on_error"] == "true": 73 | print(f"::error file:main.py::{process.stdout.decode('utf-8')}") 74 | sys.exit(1) 75 | 76 | print(process.stdout.decode("utf-8")) 77 | print(process.stderr.decode("utf-8"), file=sys.stderr) 78 | 79 | 80 | if __name__ == "__main__": 81 | main() 82 | --------------------------------------------------------------------------------