Compare commits

..

4 Commits
v4.1.0 ... v3

Author SHA1 Message Date
Tom Hu
ab904c41d6 chore(release): bump to 3.1.6 2024-01-30 11:17:54 -08:00
Tom Hu
a8c374ae46 Revert "action.yml: Update to Node.js 20 (#1228)"
This reverts commit 9140fdcf54.
2024-01-30 11:17:26 -08:00
Tom Hu
4fe8c5f003 chore(release): bump to 3.1.5 2024-01-25 10:44:09 -08:00
Robin Hallabro-Kokko
9140fdcf54 action.yml: Update to Node.js 20 (#1228)
Node.js 16 actions are deprecated.

This should suppress the deprecation notice: Please update the following actions to use Node.js 20: codecov/codecov-action@v3
2024-01-25 10:41:05 -08:00
19 changed files with 27367 additions and 31299 deletions

View File

@@ -37,11 +37,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4.1.1 uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3.24.5 uses: github/codeql-action/init@v2
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@@ -52,7 +52,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v3.24.5 uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@@ -66,4 +66,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3.24.5 uses: github/codeql-action/analyze@v2

View File

@@ -1,14 +0,0 @@
name: Enforce License Compliance
on:
pull_request:
branches: [main, master]
jobs:
enforce-license-compliance:
runs-on: ubuntu-latest
steps:
- name: 'Enforce License Compliance'
uses: getsentry/action-enforce-license-compliance@57ba820387a1a9315a46115ee276b2968da51f3d # main
with:
fossa_api_key: ${{ secrets.FOSSA_API_KEY }}

View File

@@ -1,14 +1,46 @@
name: Workflow for Codecov Action name: Workflow for Codecov Action
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
no-deps:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Upload coverage to Codecov (script)
uses: ./
with:
files: ./coverage/script/coverage-final.json
flags: script,${{ matrix.os }}
name: codecov-script
verbose: true
- name: Upload coverage to Codecov (demo)
uses: ./
with:
files: ./coverage/calculator/coverage-final.json,./coverage/coverage-test/coverage-final.json
file: ./coverage/coverage-final.json
flags: demo,${{ matrix.os }}
name: codecov-demo
verbose: true
- name: Upload coverage to Codecov (version)
uses: ./
with:
files: ./coverage/calculator/coverage-final.json,./coverage/coverage-test/coverage-final.json
file: ./coverage/coverage-final.json
flags: version,${{ matrix.os }}
name: codecov-version
version: v0.1.0_8880
verbose: true
run: run:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [macos-latest, windows-latest, ubuntu-latest, macos-latest-xlarge] os: [macos-latest, windows-latest, ubuntu-latest]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4.1.1 uses: actions/checkout@v3
- name: Install dependencies - name: Install dependencies
run: npm install run: npm install
- name: Lint - name: Lint
@@ -22,7 +54,6 @@ jobs:
flags: script,${{ matrix.os }} flags: script,${{ matrix.os }}
name: codecov-script name: codecov-script
verbose: true verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload coverage to Codecov (demo) - name: Upload coverage to Codecov (demo)
uses: ./ uses: ./
with: with:
@@ -31,7 +62,6 @@ jobs:
flags: demo,${{ matrix.os }} flags: demo,${{ matrix.os }}
name: codecov-demo name: codecov-demo
verbose: true verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload coverage to Codecov (version) - name: Upload coverage to Codecov (version)
uses: ./ uses: ./
with: with:
@@ -39,46 +69,5 @@ jobs:
file: ./coverage/coverage-final.json file: ./coverage/coverage-final.json
flags: version,${{ matrix.os }} flags: version,${{ matrix.os }}
name: codecov-version name: codecov-version
version: v0.2.0 version: v0.1.0_8880
verbose: true verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
run-container:
runs-on: ubuntu-latest
container: node:18
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
- name: Install dependencies
run: npm install
- name: Lint
run: npm run lint
- name: Run tests and collect coverage
run: npm run test
- name: Upload coverage to Codecov (script)
uses: ./
with:
files: ./coverage/script/coverage-final.json
flags: script,${{ matrix.os }}
name: codecov-script
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload coverage to Codecov (demo)
uses: ./
with:
files: ./coverage/calculator/coverage-final.json,./coverage/coverage-test/coverage-final.json
file: ./coverage/coverage-final.json
flags: demo,${{ matrix.os }}
name: codecov-demo
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload coverage to Codecov (version)
uses: ./
with:
files: ./coverage/calculator/coverage-final.json,./coverage/coverage-test/coverage-final.json
file: ./coverage/coverage-final.json
flags: version,${{ matrix.os }}
name: codecov-version
version: v0.2.0
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -24,12 +24,12 @@ jobs:
steps: steps:
- name: "Checkout code" - name: "Checkout code"
uses: actions/checkout@v4.1.1 # v3.0.0 uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0
with: with:
persist-credentials: false persist-credentials: false
- name: "Run analysis" - name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 uses: ossf/scorecard-action@80e868c13c90f172d68d1f4501dee99e2479f7af # v2.1.3
with: with:
results_file: results.sarif results_file: results.sarif
results_format: sarif results_format: sarif
@@ -48,7 +48,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab. # format to the repository Actions tab.
- name: "Upload artifact" - name: "Upload artifact"
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with: with:
name: SARIF file name: SARIF file
path: results.sarif path: results.sarif
@@ -56,6 +56,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard. # Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning" - name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@v3.24.5 # v1.0.26 uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26
with: with:
sarif_file: results.sarif sarif_file: results.sarif

View File

@@ -1,16 +1,3 @@
## 4.0.0-beta.2
### Fixes
- #1085 not adding -n if empty to do-upload command
## 4.0.0-beta.1
`v4` represents a move from the [universal uploader](https://github.com/codecov/uploader) to the [Codecov CLI](https://github.com/codecov/codecov-cli). Although this will unlock new features for our users, the CLI is not yet at feature parity with the universal uploader.
### Breaking Changes
- No current support for `aarch64` and `alpine` architectures.
- Tokenless uploading is unsuported
- Various arguments to the Action have been removed
## 3.1.4 ## 3.1.4
### Fixes ### Fixes
- #967 Fix typo in README.md - #967 Fix typo in README.md

View File

@@ -1,7 +1,7 @@
deploy: deploy:
$(eval VERSION := $(shell cat package.json | grep '"version": ' | cut -d\" -f4)) $(eval VERSION := $(shell cat package.json | grep '"version": ' | cut -d\" -f4))
git tag -d v4 git tag -d v3
git push origin :v4 git push origin :v3
git tag v4 git tag v3
git tag v$(VERSION) -s -m "" git tag v$(VERSION) -s -m ""
git push origin --tags git push origin --tags

137
README.md
View File

@@ -1,107 +1,94 @@
# Codecov GitHub Action # Codecov GitHub Action
[![GitHub Marketplace](https://img.shields.io/badge/Marketplace-v4-undefined.svg?logo=github&logoColor=white&style=flat)](https://github.com/marketplace/actions/codecov) [![GitHub Marketplace](https://img.shields.io/badge/Marketplace-v3-undefined.svg?logo=github&logoColor=white&style=flat)](https://github.com/marketplace/actions/codecov)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-action.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-action?ref=badge_shield) [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-action.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-action?ref=badge_shield)
[![Workflow for Codecov Action](https://github.com/codecov/codecov-action/actions/workflows/main.yml/badge.svg)](https://github.com/codecov/codecov-action/actions/workflows/main.yml) [![Workflow for Codecov Action](https://github.com/codecov/codecov-action/actions/workflows/main.yml/badge.svg)](https://github.com/codecov/codecov-action/actions/workflows/main.yml)
### Easily upload coverage reports to Codecov from GitHub Actions ### Easily upload coverage reports to Codecov from GitHub Actions
## v4 Release >The latest release of this Action adds support for tokenless uploads from GitHub Actions!
`v4` of the Codecov GitHub Action will use the [Codecov CLI](https://github.com/codecov/codecov-cli) to upload coverage reports to Codecov.
### Breaking Changes ## ⚠️ Deprecation of v1
- Tokenless uploading is unsupported. However, PRs made from forks to the upstream public repos will support tokenless (e.g. contributors to OS projects do not need the upstream repo's Codecov token) **As of February 1, 2022, v1 has been fully sunset and no longer functions**
- Various arguments to the Action have been removed
### Dependabot Due to the [deprecation](https://about.codecov.io/blog/introducing-codecovs-new-uploader/) of the underlying bash uploader,
- For repositories using `Dependabot`, users will need to ensure that it has access to the Codecov token for PRs from Dependabot to upload coverage. To do this, please add your `CODECOV_TOKEN` as a Dependabot Secret. For more information, see ["Configuring access to private registries for Dependabot."](https://docs.github.com/en/code-security/dependabot/working-with-dependabot/configuring-access-to-private-registries-for-dependabot#storing-credentials-for-dependabot-to-use) the Codecov GitHub Action has released `v2`/`v3` which will use the new [uploader](https://github.com/codecov/uploader). You can learn
more about our deprecation plan and the new uploader on our [blog](https://about.codecov.io/blog/introducing-codecovs-new-uploader/).
`v3` versions and below will not have access to CLI features (e.g. global upload token, ATS). We will be restricting any updates to the `v1` Action to security updates and hotfixes.
### Migration from `v1` to `v3`
The `v3` uploader has a few breaking changes for users
- Multiple fields have not been transferred from the bash uploader or have been deprecated. Notably
many of the `functionalities` and `gcov_` arguments have been removed. Please check the documentation
below for the full list.
## Usage ## Usage
To integrate Codecov with your Actions pipeline, specify the name of this repository with a tag number (`@v4` is recommended) as a `step` within your `workflow.yml` file. To integrate Codecov with your Actions pipeline, specify the name of this repository with a tag number (`@v3` is recommended) as a `step` within your `workflow.yml` file.
This Action also requires you to [provide an upload token](https://docs.codecov.io/docs/frequently-asked-questions#section-where-is-the-repository-upload-token-found-) from [codecov.io](https://www.codecov.io) (tip: in order to avoid exposing your token, [store it](https://docs.codecov.com/docs/adding-the-codecov-token#github-actions) as a `secret`). If you have a *private repository*, this Action also requires you to [provide an upload token](https://docs.codecov.io/docs/frequently-asked-questions#section-where-is-the-repository-upload-token-found-) from [codecov.io](https://www.codecov.io) (tip: in order to avoid exposing your token, store it as a `secret`). Optionally, you can choose to include up to four additional inputs to customize the upload context. **For public repositories, no token is needed**
Currently, the Action will identify linux, macos, and windows runners. However, the Action may misidentify other architectures. The OS can be specified as
- alpine
- alpine-arm64
- linux
- linux-arm64
- macos
- windows
Inside your `.github/workflows/workflow.yml` file: Inside your `.github/workflows/workflow.yml` file:
```yaml ```yaml
steps: steps:
- uses: actions/checkout@master - uses: actions/checkout@master
- uses: codecov/codecov-action@v4 - uses: codecov/codecov-action@v3
with: with:
fail_ci_if_error: true # optional (default = false) token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage1.xml,./coverage2.xml # optional files: ./coverage1.xml,./coverage2.xml # optional
flags: unittests # optional flags: unittests # optional
name: codecov-umbrella # optional name: codecov-umbrella # optional
token: ${{ secrets.CODECOV_TOKEN }} # required
verbose: true # optional (default = false)
```
The Codecov token can also be passed in via environment variables:
```yaml
steps:
- uses: actions/checkout@master
- uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true # optional (default = false) fail_ci_if_error: true # optional (default = false)
files: ./coverage1.xml,./coverage2.xml # optional
flags: unittests # optional
name: codecov-umbrella # optional
verbose: true # optional (default = false) verbose: true # optional (default = false)
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
``` ```
> [!NOTE] >**Note**: This assumes that you've set your Codecov token inside *Settings > Secrets* as `CODECOV_TOKEN`. If not, you can [get an upload token](https://docs.codecov.io/docs/frequently-asked-questions#section-where-is-the-repository-upload-token-found-) for your specific repo on [codecov.io](https://www.codecov.io). Keep in mind that secrets are *not* available to forks of repositories.
> This assumes that you've set your Codecov token inside *Settings > Secrets* as `CODECOV_TOKEN`. If not, you can [get an upload token](https://docs.codecov.io/docs/frequently-asked-questions#section-where-is-the-repository-upload-token-found-) for your specific repo on [codecov.io](https://www.codecov.io). Keep in mind that secrets are *not* available to forks of repositories.
## Arguments ## Arguments
Codecov's Action supports inputs from the user. These inputs, along with their descriptions and usage contexts, are listed in the table below: Codecov's Action supports inputs from the user. These inputs, along with their descriptions and usage contexts, are listed in the table below:
| Input | Description | Required | | Input | Description | Usage |
| :--- | :--- | :---: | | :---: | :---: | :---: |
| `token` | Repository Codecov token. Used to authorize report uploads | *Required | `token` | Used to authorize coverage report uploads | *Required |
| `codecov_yml_path` | Specify the path to the Codecov YML | Optional | `move_coverage_to_trash` | Move discovered coverage reports to the trash | Optional
| `commit_parent` | Override to specify the parent commit SHA | Optional | `commit_parent` | The commit SHA of the parent for which you are uploading coverage. If not present, the parent will be determined using the API of your repository provider. When using the repository provider's API, the parent is determined via finding the closest ancestor to the commit. | Optional
| `directory` | Directory to search for coverage reports. | Optional | `dry_run` | Don't upload files to Codecov | Optional
| `disable_search` | Disable search for coverage files. This is helpful when specifying what files you want to upload with the --file option. | Optional | `env_vars` | Environment variables to tag the upload with. Multiple env variables can be separated with commas (e.g. `OS,PYTHON`) | Optional
| `disable_file_fixes` | Disable file fixes to ignore common lines from coverage (e.g. blank lines or empty brackets) | Optional | `fail_ci_if_error` | Specify if CI pipeline should fail when Codecov runs into errors during upload. *Defaults to **false*** | Optional
| `dry_run` | Don't upload files to Codecov | Optional | `files` | Comma-separated paths to the coverage report(s). Negated paths are supported by starting with `!` | Optional
| `env_vars` | Environment variables to tag the upload with (e.g. PYTHON \| OS,PYTHON) | Optional | `flags` | Flag the upload to group coverage metrics (unittests, uitests, etc.). Multiple flags are separated by a comma (ui,chrome) | Optional
| `exclude` | Folders to exclude from search | Optional | `full_report` | Specify the path of a full Codecov report to re-upload | Optional
| `fail_ci_if_error` | Specify whether or not CI build should fail if Codecov runs into an error during upload | Optional | `functionalities` | Toggle functionalities | Optional
| `file` | Path to coverage file to upload | Optional | -- `network` | Disable uploading the file network | Optional
| `files` | Comma-separated list of files to upload | Optional | -- `fixes` | Enable file fixes to ignore common lines from coverage | Optional
| `flags` | Flag upload to group coverage metrics (e.g. unittests \| integration \| ui,chrome) | Optional | -- `search` | Disable searching for coverage files | Optional
| `handle_no_reports_found` | Raise no exceptions when no coverage reports found | Optional | `gcov` | Run with gcov support | Optional
| `job_code` | The job code | Optional | `gcov_args` | Extra arguments to pass to gcov | Optional
| `name` | User defined upload name. Visible in Codecov UI | Optional | `gcov_ignore` | Paths to ignore during gcov gathering | Optional
| `os` | Override the assumed OS. Options are linux \| macos \| windows \| . | Optional | `gcov_include` | Paths to include during gcov gathering | Optional
| `override_branch` | Specify the branch name | Optional | `gcov_executable` | gcov executable to run. Defaults to gcov. | Optional
| `override_build` | Specify the build number | Optional | `name` | Custom defined name for the upload | Optional
| `override_build_url` | The URL of the build where this is running | Optional | `network_filter` | Specify a filter on the files listed in the network section of the Codecov report. Useful for upload-specific path fixing | Optional
| `override_commit` | Specify the commit SHA | Optional | `network_prefix` | Specify a prefix on files listed in the network section of the Codecov report. Useful to help resolve path fixing | Optional
| `override_pr` | Specify the pull request number | Optional | `os` | Specify the OS (linux, macos, windows, alpine) | Optional
| `plugin` | plugins to run. Options: xcode, gcov, pycoverage. The default behavior runs them all. | Optional | `override_branch` | Specify the branch name | Optional
| `plugins` | Comma-separated list of plugins for use during upload. | Optional | `override_build` | Specify the build number | Optional
| `report_code` | The code of the report. If unsure, do not include | Optional | `override_commit` | Specify the commit SHA | Optional
| `root_dir` | Used when not in git/hg project to identify project root directory | Optional | `override_pr` | Specify the pull request number | Optional
| `slug` | Specify the slug manually (Enterprise use) | Optional | `override_tag` | Specify the git tag | Optional
| `url` | Specify the base url to upload (Enterprise use) | Optional | `root_dir` | Used when not in git/hg project to identify project root directory | Optional
| `use_legacy_upload_endpoint` | Use the legacy upload endpoint | Optional | `directory` | Directory to search for coverage reports. | Optional
| `verbose` | Specify whether the Codecov output should be verbose | Optional | `slug` | Specify the slug manually (Enterprise use) | Optional
| `version` | Specify which version of the Codecov CLI should be used. Defaults to `latest` | Optional | `swift` | Run with swift coverage support | Optional
| `working-directory` | Directory in which to execute codecov.sh | Optional | -- `swift_project` | Specify the swift project to speed up coverage conversion | Optional
| `upstream_proxy` | The upstream http proxy server to connect through | Optional
| `url` | Change the upload host (Enterprise use) | Optional
| `verbose` | Specify whether the Codecov output should be verbose | Optional
| `version` | Specify which version of the Codecov Uploader should be used. Defaults to `latest` | Optional
| `working-directory` | Directory in which to execute `codecov.sh` | Optional
| `xtra_args` | Add additional uploader args that may be missing in the Action | Optional
### Example `workflow.yml` with Codecov Action ### Example `workflow.yml` with Codecov Action
@@ -129,15 +116,15 @@ jobs:
pip install pytest-cov pip install pytest-cov
pytest --cov=./ --cov-report=xml pytest --cov=./ --cov-report=xml
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
uses: codecov/codecov-action@v4 uses: codecov/codecov-action@v3
with: with:
token: ${{ secrets.CODECOV_TOKEN }}
directory: ./coverage/reports/ directory: ./coverage/reports/
env_vars: OS,PYTHON env_vars: OS,PYTHON
fail_ci_if_error: true fail_ci_if_error: true
files: ./coverage1.xml,./coverage2.xml,!./cache files: ./coverage1.xml,./coverage2.xml,!./cache
flags: unittests flags: unittests
name: codecov-umbrella name: codecov-umbrella
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true verbose: true
``` ```
## Contributing ## Contributing

View File

@@ -3,37 +3,7 @@ description: 'GitHub Action that uploads coverage reports for your repository to
author: 'Ibrahim Ali <@ibrahim0814> & Thomas Hu <@thomasrockhu> | Codecov' author: 'Ibrahim Ali <@ibrahim0814> & Thomas Hu <@thomasrockhu> | Codecov'
inputs: inputs:
token: token:
description: 'Repository Codecov token. Used to authorize report uploads' description: 'Repository upload token - get it from codecov.io. Required only for private repositories'
required: false
codecov_yml_path:
description: 'Specify the path to the Codecov YML'
required: false
commit_parent:
description: 'Override to specify the parent commit SHA'
required: false
directory:
description: 'Directory to search for coverage reports.'
required: false
disable_file_fixes:
description: 'Disable file fixes to ignore common lines from coverage (e.g. blank lines or empty brackets)'
required: false
disable_search:
description: 'Disable search for coverage files. This is helpful when specifying what files you want to upload with the --file option.'
required: false
disable_safe_directory:
description: 'Disable setting safe directory. Set to true to disable.'
required: false
dry_run:
description: "Don't upload files to Codecov"
required: false
env_vars:
description: 'Environment variables to tag the upload with (e.g. PYTHON | OS,PYTHON)'
required: false
exclude:
description: 'Folders to exclude from search'
required: false
fail_ci_if_error:
description: 'Specify whether or not CI build should fail if Codecov runs into an error during upload'
required: false required: false
file: file:
description: 'Path to coverage file to upload' description: 'Path to coverage file to upload'
@@ -41,23 +11,59 @@ inputs:
files: files:
description: 'Comma-separated list of files to upload' description: 'Comma-separated list of files to upload'
required: false required: false
directory:
description: 'Directory to search for coverage reports.'
required: false
flags: flags:
description: 'Flag upload to group coverage metrics (e.g. unittests | integration | ui,chrome)' description: 'Flag upload to group coverage metrics (e.g. unittests | integration | ui,chrome)'
required: false required: false
git_service: full_report:
description: 'Override the git_service (e.g. github_enterprise)' description: Specify the path of a full Codecov report to re-upload
required: false required: false
handle_no_reports_found: commit_parent:
description: 'Raise no exceptions when no coverage reports found' description: 'The commit SHA of the parent for which you are uploading coverage. If not present, the parent will be determined using the API of your repository provider. When using the repository providers API, the parent is determined via finding the closest ancestor to the commit.'
required: false required: false
job_code: dry_run:
description: 'The job code' description: "Don't upload files to Codecov"
required: false
env_vars:
description: 'Environment variables to tag the upload with (e.g. PYTHON | OS,PYTHON)'
required: false
fail_ci_if_error:
description: 'Specify whether or not CI build should fail if Codecov runs into an error during upload'
required: false
functionalities:
description: 'Comma-separated list, see the README for options and their usage. Options include `network`, `fixes`, `search`.'
required: false
gcov:
description: 'Run with gcov support'
required: false
gcov_args:
description: 'Extra arguments to pass to gcov'
required: false
gcov_executable:
description: 'gcov executable to run. Defaults to gcov'
required: false
gcov_ignore:
description: 'Paths to ignore during gcov gathering'
required: false
gcov_include:
description: 'Paths to include during gcov gathering'
required: false
move_coverage_to_trash:
description: 'Move discovered coverage reports to the trash'
required: false required: false
name: name:
description: 'User defined upload name. Visible in Codecov UI' description: 'User defined upload name. Visible in Codecov UI'
required: false required: false
network_filter:
description: 'Specify a filter on the files listed in the network section of the Codecov report. Useful for upload-specific path fixing'
required: false
network_prefix:
description: 'Specify a prefix on files listed in the network section of the Codecov report. Useful to help resolve path fixing'
required: false
os: os:
description: 'Override the assumed OS. Options are linux | macos | windows.' description: 'Override the assumed OS. Options are aarch64 | alpine | linux | macos | windows.'
required: false required: false
override_branch: override_branch:
description: 'Specify the branch name' description: 'Specify the branch name'
@@ -65,23 +71,14 @@ inputs:
override_build: override_build:
description: 'Specify the build number' description: 'Specify the build number'
required: false required: false
override_build_url:
description: 'The URL of the build where this is running'
required: false
override_commit: override_commit:
description: 'Specify the commit SHA' description: 'Specify the commit SHA'
required: false required: false
override_pr: override_pr:
description: 'Specify the pull request number' description: 'Specify the pull request number'
required: false required: false
plugin: override_tag:
description: 'plugins to run. Options: xcode, gcov, pycoverage. The default behavior runs them all.' description: 'Specify the git tag'
required: false
plugins:
description: 'Comma-separated list of plugins for use during upload.'
required: false
report_code:
description: 'The code of the report. If unsure, do not include'
required: false required: false
root_dir: root_dir:
description: 'Used when not in git/hg project to identify project root directory' description: 'Used when not in git/hg project to identify project root directory'
@@ -89,24 +86,39 @@ inputs:
slug: slug:
description: 'Specify the slug manually (Enterprise use)' description: 'Specify the slug manually (Enterprise use)'
required: false required: false
url: swift:
description: 'Specify the base url to upload (Enterprise use)' description: 'Run with swift coverage support'
required: false required: false
use_legacy_upload_endpoint: swift_project:
description: 'Use the legacy upload endpoint' description: 'Specify the swift project to speed up coverage conversion'
required: false
upstream_proxy:
description: 'The upstream http proxy server to connect through'
required: false
url:
description: 'Change the upload host (Enterprise use)'
required: false required: false
verbose: verbose:
description: 'Specify whether the Codecov output should be verbose' description: 'Specify whether the Codecov output should be verbose'
required: false required: false
version: version:
description: 'Specify which version of the Codecov CLI should be used. Defaults to `latest`' description: 'Specify which version of the Codecov Uploader should be used. Defaults to `latest`'
required: false required: false
working-directory: working-directory:
description: 'Directory in which to execute codecov.sh' description: 'Directory in which to execute codecov.sh'
required: false required: false
xcode:
description: 'Run with xcode support'
required: false
xcode_archive_path:
description: 'Specify the xcode archive path. Likely specified as the -resultBundlePath and should end in .xcresult'
required: false
xtra_args:
description: 'Add additional uploader args that may be missing in the Action'
required: false
branding: branding:
color: 'red' color: 'red'
icon: 'umbrella' icon: 'umbrella'
runs: runs:
using: 'node20' using: 'node16'
main: 'dist/index.js' main: 'dist/index.js'

45451
dist/index.js vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

11821
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "codecov-action", "name": "codecov-action",
"version": "4.1.0", "version": "3.1.6",
"description": "Upload coverage reports to Codecov from GitHub Actions", "description": "Upload coverage reports to Codecov from GitHub Actions",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -23,22 +23,23 @@
}, },
"homepage": "https://github.com/codecov/codecov-action#readme", "homepage": "https://github.com/codecov/codecov-action#readme",
"dependencies": { "dependencies": {
"@actions/core": "^1.10.1", "@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1", "@actions/exec": "^1.1.1",
"@actions/github": "^6.0.0", "@actions/github": "^5.1.1",
"gpg": "^0.6.0", "node-fetch": "^3.3.1",
"undici": "5.28.2" "openpgp": "5.8"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.12", "@types/jest": "^27.5.0",
"@typescript-eslint/eslint-plugin": "^7.0.0", "@types/node": "^20.1.4",
"@typescript-eslint/parser": "^6.21.0", "@typescript-eslint/eslint-plugin": "^4.29.2",
"@vercel/ncc": "^0.38.1", "@typescript-eslint/parser": "^4.29.2",
"eslint": "^8.57.0", "@vercel/ncc": "^0.36.1",
"eslint": "^7.32.0",
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
"jest": "^29.7.0", "jest": "^26.6.3",
"jest-junit": "^16.0.0", "jest-junit": "^16.0.0",
"ts-jest": "^29.1.2", "ts-jest": "^26.5.6",
"typescript": "^5.3.3" "typescript": "^4.9.5"
} }
} }

View File

@@ -1,108 +1,85 @@
import * as github from '@actions/github'; import * as github from '@actions/github';
import { import buildExec from './buildExec';
buildCommitExec,
buildGeneralExec,
buildReportExec,
buildUploadExec,
} from './buildExec';
/* eslint-disable @typescript-eslint/no-var-requires */
const {version} = require('../package.json');
const context = github.context; const context = github.context;
test('general args', () => { test('no arguments', () => {
const envs = { const {execArgs, failCi} = buildExec();
codecov_yml_path: 'dev/codecov.yml',
url: 'https://codecov.enterprise.com',
verbose: 't',
};
for (const env of Object.keys(envs)) {
process.env['INPUT_' + env.toUpperCase()] = envs[env];
}
const {args, verbose} = buildGeneralExec(); const args = [
'-n',
expect(args).toEqual( '',
expect.arrayContaining([ '-Q',
'--codecov-yml-path', `github-action-${version}`,
'dev/codecov.yml',
'--enterprise-url',
'https://codecov.enterprise.com',
'-v',
]));
expect(verbose).toBeTruthy();
for (const env of Object.keys(envs)) {
delete process.env['INPUT_' + env.toUpperCase()];
}
});
test('upload args using context', () => {
const expectedArgs = [
'--git-service',
'github',
]; ];
const {uploadExecArgs, uploadCommand} = buildUploadExec();
if (context.eventName == 'pull_request') { if (context.eventName == 'pull_request') {
expectedArgs.push('-C', `${context.payload.pull_request.head.sha}`); args.push('-C', `${context.payload.pull_request.head.sha}`);
} }
if (context.eventName == 'pull_request_target') { expect(execArgs).toEqual(args);
expectedArgs.push('-P', `${context.payload.number}`); expect(failCi).toBeFalsy();
}
expect(uploadExecArgs).toEqual(expectedArgs);
expect(uploadCommand).toEqual('do-upload');
}); });
test('upload args', () => { test('all arguments', () => {
const envs = { const envs = {
'codecov_yml_path': 'dev/codecov.yml', 'commit_parent': '83231650328f11695dfb754ca0f540516f188d27',
'commit_parent': 'fakeparentcommit',
'directory': 'coverage/', 'directory': 'coverage/',
'disable_file_fixes': 'true',
'disable_search': 'true',
'dry_run': 'true', 'dry_run': 'true',
'env_vars': 'OS,PYTHON', 'env_vars': 'OS,PYTHON',
'exclude': 'node_modules/',
'fail_ci_if_error': 'true', 'fail_ci_if_error': 'true',
'file': 'coverage.xml', 'file': 'coverage.xml',
'files': 'dir1/coverage.xml,dir2/coverage.xml', 'files': 'dir1/coverage.xml,dir2/coverage.xml',
'flags': 'test,test2', 'flags': 'test,test2',
'git_service': 'github_enterprise', 'functionalities': 'network',
'handle_no_reports_found': 'true', 'full_report': 'oldDir/oldReport.json',
'job_code': '32', 'gcov': 'true',
'gcov_args': '-v',
'gcov_ignore': '*.fake',
'gcov_include': 'real_file',
'gcov_executable': 'gcov2',
'move_coverage_to_trash': 'true',
'name': 'codecov', 'name': 'codecov',
'os': 'macos', 'network_filter': 'src/',
'network_prefix': 'build/',
'override_branch': 'thomasrockhu/test', 'override_branch': 'thomasrockhu/test',
'override_build': '1', 'override_build': '1',
'override_build_url': 'https://example.com/build/2',
'override_commit': '9caabca5474b49de74ef5667deabaf74cdacc244', 'override_commit': '9caabca5474b49de74ef5667deabaf74cdacc244',
'override_pr': '2', 'override_pr': '2',
'plugin': 'xcode', 'override_tag': 'v1.2',
'plugins': 'pycoverage,compress-pycoverage',
'report_code': 'testCode',
'root_dir': 'root/', 'root_dir': 'root/',
'swift': 'true',
'swift_project': 'MyApp',
'slug': 'fakeOwner/fakeRepo', 'slug': 'fakeOwner/fakeRepo',
'token': 'd3859757-ab80-4664-924d-aef22fa7557b', 'token': 'd3859757-ab80-4664-924d-aef22fa7557b',
'url': 'https://enterprise.example.com', 'upstream_proxy': 'https://codecov.example.com',
'use_legacy_upload_endpoint': 'true', 'url': 'https://codecov.enterprise.com',
'verbose': 'true', 'verbose': 't',
'version': '0.1.2', 'xcode': 'true',
'working-directory': 'src', 'xcode_archive_path': '/test.xcresult',
'xtra_args': '--some --other --args',
}; };
for (const env of Object.keys(envs)) { for (const env of Object.keys(envs)) {
process.env['INPUT_' + env.toUpperCase()] = envs[env]; process.env['INPUT_' + env.toUpperCase()] = envs[env];
} }
const {uploadExecArgs, uploadCommand} = buildUploadExec(); const {execArgs, failCi} = buildExec();
const expectedArgs = [ expect(execArgs).toEqual([
'--disable-file-fixes', '-n',
'--disable-search', 'codecov',
'-Q',
`github-action-${version}`,
'-c',
'-N',
'83231650328f11695dfb754ca0f540516f188d27',
'-d', '-d',
'-e', '-e',
'OS,PYTHON', 'OS,PYTHON',
'--exclude', '-X',
'node_modules/', 'network',
'-Z', '-Z',
'-f', '-f',
'coverage.xml', 'coverage.xml',
@@ -110,165 +87,138 @@ test('upload args', () => {
'dir1/coverage.xml', 'dir1/coverage.xml',
'-f', '-f',
'dir2/coverage.xml', 'dir2/coverage.xml',
'--full',
'oldDir/oldReport.json',
'-F', '-F',
'test', 'test',
'-F', '-F',
'test2', 'test2',
'--git-service', '-g',
'github_enterprise', '--ga',
'--handle-no-reports-found', '-v',
'--job-code', '--gi',
'32', '*.fake',
'-n', '--gI',
'codecov', 'real_file',
'--gx',
'gcov2',
'-i',
'src/',
'-k',
'build/',
'-B', '-B',
'thomasrockhu/test', 'thomasrockhu/test',
'-b', '-b',
'1', '1',
'--build-url',
'https://example.com/build/2',
'-C', '-C',
'9caabca5474b49de74ef5667deabaf74cdacc244', '9caabca5474b49de74ef5667deabaf74cdacc244',
'-P', '-P',
'2', '2',
'--plugin', '-T',
'xcode', 'v1.2',
'--plugin', '-R',
'pycoverage',
'--plugin',
'compress-pycoverage',
'--report-code',
'testCode',
'--network-root-folder',
'root/', 'root/',
'-s', '-s',
'coverage/', 'coverage/',
'-r', '-r',
'fakeOwner/fakeRepo', 'fakeOwner/fakeRepo',
'--legacy', '--xs',
]; '--xsp',
'MyApp',
'-U',
'https://codecov.example.com',
'-u',
'https://codecov.enterprise.com',
'-v',
'--xc',
'--xp',
'/test.xcresult',
'--some --other --args',
]);
expect(failCi).toBeTruthy();
expect(uploadExecArgs).toEqual(expectedArgs);
expect(uploadCommand).toEqual('do-upload');
for (const env of Object.keys(envs)) { for (const env of Object.keys(envs)) {
delete process.env['INPUT_' + env.toUpperCase()]; delete process.env['INPUT_' + env.toUpperCase()];
} }
}); });
describe('trim arguments after splitting them', () => {
test('report args', () => { const baseExpectation = [
const envs = { '-n',
git_service: 'github_enterprise', expect.stringContaining(''),
override_commit: '9caabca5474b49de74ef5667deabaf74cdacc244', '-Q',
override_pr: 'fakePR', expect.stringContaining('github-action'),
slug: 'fakeOwner/fakeRepo',
token: 'd3859757-ab80-4664-924d-aef22fa7557b',
fail_ci_if_error: 'true',
};
for (const env of Object.keys(envs)) {
process.env['INPUT_' + env.toUpperCase()] = envs[env];
}
const {reportExecArgs, reportCommand} = buildReportExec();
const expectedArgs = [
'--git-service',
'github_enterprise',
'-C',
'9caabca5474b49de74ef5667deabaf74cdacc244',
'-P',
'fakePR',
'--slug',
'fakeOwner/fakeRepo',
'-Z',
]; ];
expect(reportExecArgs).toEqual(expectedArgs); test('files', () => {
expect(reportCommand).toEqual('create-report'); const envs = {'files': './client-coverage.txt, ./lcov.info'};
for (const env of Object.keys(envs)) {
delete process.env['INPUT_' + env.toUpperCase()]; for (const [name, value] of Object.entries(envs)) {
} process.env['INPUT_' + name.toUpperCase()] = value;
}); }
const {execArgs} = buildExec();
test('report args using context', () => {
const envs = { expect(execArgs).toEqual(
token: 'd3859757-ab80-4664-924d-aef22fa7557b', expect.arrayContaining([
}; ...baseExpectation,
for (const env of Object.keys(envs)) { '-f',
process.env['INPUT_' + env.toUpperCase()] = envs[env]; './client-coverage.txt',
} '-f',
const expectedArgs : string[] = [ './lcov.info',
'--git-service', ]),
'github', );
];
if (context.eventName == 'pull_request') { for (const env of Object.keys(envs)) {
expectedArgs.push('-C', `${context.payload.pull_request.head.sha}`); delete process.env['INPUT_' + env.toUpperCase()];
} }
});
const {reportExecArgs, reportCommand} = buildReportExec();
test('flags', () => {
expect(reportExecArgs).toEqual(expectedArgs); const envs = {'flags': 'ios, mobile'};
expect(reportCommand).toEqual('create-report');
for (const env of Object.keys(envs)) { for (const [name, value] of Object.entries(envs)) {
delete process.env['INPUT_' + env.toUpperCase()]; process.env['INPUT_' + name.toUpperCase()] = value;
} }
});
const {execArgs} = buildExec();
test('commit args', () => { expect(execArgs).toEqual(
const envs = { expect.arrayContaining([
git_service: 'github_enterprise', ...baseExpectation,
commit_parent: '83231650328f11695dfb754ca0f540516f188d27', '-F',
override_branch: 'thomasrockhu/test', 'ios',
override_commit: '9caabca5474b49de74ef5667deabaf74cdacc244', '-F',
override_pr: '2', 'mobile',
slug: 'fakeOwner/fakeRepo', ]),
token: 'd3859757-ab80-4664-924d-aef22fa7557b', );
fail_ci_if_error: 'true',
}; for (const env of Object.keys(envs)) {
for (const env of Object.keys(envs)) { delete process.env['INPUT_' + env.toUpperCase()];
process.env['INPUT_' + env.toUpperCase()] = envs[env]; }
} });
const {commitExecArgs, commitCommand} = buildCommitExec(); test('functionalities', () => {
const expectedArgs = [ const envs = {'functionalities': 'network, gcov'};
'--parent-sha',
'83231650328f11695dfb754ca0f540516f188d27', for (const [name, value] of Object.entries(envs)) {
'--git-service', process.env['INPUT_' + name.toUpperCase()] = value;
'github_enterprise', }
'-B',
'thomasrockhu/test', const {execArgs} = buildExec();
'-C',
'9caabca5474b49de74ef5667deabaf74cdacc244', expect(execArgs).toEqual(
'--pr', expect.arrayContaining([
'2', ...baseExpectation,
'--slug', '-X',
'fakeOwner/fakeRepo', 'network',
'-Z', '-X',
]; 'gcov',
]),
expect(commitExecArgs).toEqual(expectedArgs); );
expect(commitCommand).toEqual('create-commit');
for (const env of Object.keys(envs)) { for (const env of Object.keys(envs)) {
delete process.env['INPUT_' + env.toUpperCase()]; delete process.env['INPUT_' + env.toUpperCase()];
} }
}); });
test('commit args using context', () => {
const expectedArgs :string[] = [
'--git-service',
'github',
];
const {commitExecArgs, commitCommand} = buildCommitExec();
if (context.eventName == 'pull_request') {
expectedArgs.push('-C', `${context.payload.pull_request.head.sha}`);
}
if (context.eventName == 'pull_request_target') {
expectedArgs.push('-P', `${context.payload.number}`);
}
expect(commitExecArgs).toEqual(expectedArgs);
expect(commitCommand).toEqual('create-commit');
}); });

View File

@@ -1,8 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as github from '@actions/github'; import * as github from '@actions/github';
import {version} from '../package.json';
const context = github.context; const context = github.context;
@@ -17,185 +16,56 @@ const isTrue = (variable) => {
); );
}; };
const buildExec = () => {
const buildCommitExec = () => { const clean = core.getInput('move_coverage_to_trash');
const commitParent = core.getInput('commit_parent'); const commitParent = core.getInput('commit_parent');
const gitService = core.getInput('git_service');
const overrideBranch = core.getInput('override_branch');
const overrideCommit = core.getInput('override_commit');
const overridePr = core.getInput('override_pr');
const slug = core.getInput('slug');
const token = core.getInput('token');
const failCi = isTrue(core.getInput('fail_ci_if_error'));
const workingDir = core.getInput('working-directory');
const commitCommand = 'create-commit';
const commitExecArgs = [];
const commitOptions:any = {};
commitOptions.env = Object.assign(process.env, {
GITHUB_ACTION: process.env.GITHUB_ACTION,
GITHUB_RUN_ID: process.env.GITHUB_RUN_ID,
GITHUB_REF: process.env.GITHUB_REF,
GITHUB_REPOSITORY: process.env.GITHUB_REPOSITORY,
GITHUB_SHA: process.env.GITHUB_SHA,
GITHUB_HEAD_REF: process.env.GITHUB_HEAD_REF || '',
});
if (token) {
commitOptions.env.CODECOV_TOKEN = token;
}
if (commitParent) {
commitExecArgs.push('--parent-sha', `${commitParent}`);
}
commitExecArgs.push('--git-service', `${gitService ? gitService : 'github'}`);
if (overrideBranch) {
commitExecArgs.push('-B', `${overrideBranch}`);
}
if (overrideCommit) {
commitExecArgs.push('-C', `${overrideCommit}`);
} else if (
`${context.eventName}` == 'pull_request' ||
`${context.eventName}` == 'pull_request_target'
) {
commitExecArgs.push('-C', `${context.payload.pull_request.head.sha}`);
}
if (overridePr) {
commitExecArgs.push('--pr', `${overridePr}`);
} else if (
`${context.eventName}` == 'pull_request_target'
) {
commitExecArgs.push('--pr', `${context.payload.number}`);
}
if (slug) {
commitExecArgs.push('--slug', `${slug}`);
}
if (failCi) {
commitExecArgs.push('-Z');
}
if (workingDir) {
commitOptions.cwd = workingDir;
}
return {commitExecArgs, commitOptions, commitCommand};
};
const buildGeneralExec = () => {
const codecovYmlPath = core.getInput('codecov_yml_path');
const url = core.getInput('url');
const verbose = isTrue(core.getInput('verbose'));
const args = [];
if (codecovYmlPath) {
args.push('--codecov-yml-path', `${codecovYmlPath}`);
}
if (url) {
args.push('--enterprise-url', `${url}`);
}
if (verbose) {
args.push('-v');
}
return {args, verbose};
};
const buildReportExec = () => {
const gitService = core.getInput('git_service');
const overrideCommit = core.getInput('override_commit');
const overridePr = core.getInput('override_pr');
const slug = core.getInput('slug');
const token = core.getInput('token');
const failCi = isTrue(core.getInput('fail_ci_if_error'));
const workingDir = core.getInput('working-directory');
const reportCommand = 'create-report';
const reportExecArgs = [];
const reportOptions:any = {};
reportOptions.env = Object.assign(process.env, {
GITHUB_ACTION: process.env.GITHUB_ACTION,
GITHUB_RUN_ID: process.env.GITHUB_RUN_ID,
GITHUB_REF: process.env.GITHUB_REF,
GITHUB_REPOSITORY: process.env.GITHUB_REPOSITORY,
GITHUB_SHA: process.env.GITHUB_SHA,
GITHUB_HEAD_REF: process.env.GITHUB_HEAD_REF || '',
});
if (token) {
reportOptions.env.CODECOV_TOKEN = token;
}
reportExecArgs.push('--git-service', `${gitService ? gitService : 'github'}`);
if (overrideCommit) {
reportExecArgs.push('-C', `${overrideCommit}`);
} else if (
`${context.eventName}` == 'pull_request' ||
`${context.eventName}` == 'pull_request_target'
) {
reportExecArgs.push('-C', `${context.payload.pull_request.head.sha}`);
}
if (overridePr) {
reportExecArgs.push('-P', `${overridePr}`);
} else if (
`${context.eventName}` == 'pull_request_target'
) {
reportExecArgs.push('-P', `${context.payload.number}`);
}
if (slug) {
reportExecArgs.push('--slug', `${slug}`);
}
if (failCi) {
reportExecArgs.push('-Z');
}
if (workingDir) {
reportOptions.cwd = workingDir;
}
return {reportExecArgs, reportOptions, reportCommand};
};
const buildUploadExec = () => {
const disableFileFixes = isTrue(core.getInput('disable_file_fixes'));
const disableSafeDirectory = isTrue(core.getInput('diable_safe_directory'));
const disableSearch = isTrue(core.getInput('disable_search'));
const dryRun = isTrue(core.getInput('dry_run')); const dryRun = isTrue(core.getInput('dry_run'));
const envVars = core.getInput('env_vars'); const envVars = core.getInput('env_vars');
const exclude = core.getInput('exclude');
const failCi = isTrue(core.getInput('fail_ci_if_error')); const failCi = isTrue(core.getInput('fail_ci_if_error'));
const file = core.getInput('file'); const file = core.getInput('file');
const files = core.getInput('files'); const files = core.getInput('files');
const flags = core.getInput('flags'); const flags = core.getInput('flags');
const gitService = core.getInput('git_service'); const fullReport = core.getInput('full_report');
const handleNoReportsFound = isTrue(core.getInput('handle_no_reports_found')); const functionalities = core.getInput('functionalities');
const jobCode = core.getInput('job_code'); const gcov = core.getInput('gcov');
const gcovArgs = core.getInput('gcov_args');
const gcovExecutable = core.getInput('gcov_executable');
const gcovIgnore = core.getInput('gcov_ignore');
const gcovInclude = core.getInput('gcov_include');
const name = core.getInput('name'); const name = core.getInput('name');
const networkFilter = core.getInput('network_filter');
const networkPrefix = core.getInput('network_prefix');
const os = core.getInput('os'); const os = core.getInput('os');
const overrideBranch = core.getInput('override_branch'); const overrideBranch = core.getInput('override_branch');
const overrideBuild = core.getInput('override_build'); const overrideBuild = core.getInput('override_build');
const overrideBuildUrl = core.getInput('override_build_url');
const overrideCommit = core.getInput('override_commit'); const overrideCommit = core.getInput('override_commit');
const overridePr = core.getInput('override_pr'); const overridePr = core.getInput('override_pr');
const plugin = core.getInput('plugin'); const overrideTag = core.getInput('override_tag');
const plugins = core.getInput('plugins');
const reportCode = core.getInput('report_code');
const rootDir = core.getInput('root_dir'); const rootDir = core.getInput('root_dir');
const searchDir = core.getInput('directory'); const searchDir = core.getInput('directory');
const slug = core.getInput('slug'); const slug = core.getInput('slug');
const swift = core.getInput('swift');
const swiftProject = core.getInput('swift_project');
const token = core.getInput('token'); const token = core.getInput('token');
let uploaderVersion = core.getInput('version'); const upstream = core.getInput('upstream_proxy');
const useLegacyUploadEndpoint = isTrue( const url = core.getInput('url');
core.getInput('use_legacy_upload_endpoint'), const verbose = isTrue(core.getInput('verbose'));
);
const workingDir = core.getInput('working-directory'); const workingDir = core.getInput('working-directory');
const xcode = core.getInput('xcode');
const xcodeArchivePath = core.getInput('xcode_archive_path');
const xtraArgs = core.getInput('xtra_args');
let uploaderVersion = core.getInput('version');
const uploadExecArgs = []; const execArgs = [];
const uploadCommand = 'do-upload'; execArgs.push(
const uploadOptions:any = {}; '-n',
uploadOptions.env = Object.assign(process.env, { `${name}`,
'-Q',
`github-action-${version}`,
);
const options:any = {};
options.env = Object.assign(process.env, {
GITHUB_ACTION: process.env.GITHUB_ACTION, GITHUB_ACTION: process.env.GITHUB_ACTION,
GITHUB_RUN_ID: process.env.GITHUB_RUN_ID, GITHUB_RUN_ID: process.env.GITHUB_RUN_ID,
GITHUB_REF: process.env.GITHUB_REF, GITHUB_REF: process.env.GITHUB_REF,
@@ -208,123 +78,144 @@ const buildUploadExec = () => {
for (const envVar of envVars.split(',')) { for (const envVar of envVars.split(',')) {
const envVarClean = envVar.trim(); const envVarClean = envVar.trim();
if (envVarClean) { if (envVarClean) {
uploadOptions.env[envVarClean] = process.env[envVarClean]; options.env[envVarClean] = process.env[envVarClean];
envVarsArg.push(envVarClean); envVarsArg.push(envVarClean);
} }
} }
if (token) { if (token) {
uploadOptions.env.CODECOV_TOKEN = token; options.env.CODECOV_TOKEN = token;
} }
if (disableFileFixes) { if (clean) {
uploadExecArgs.push('--disable-file-fixes'); execArgs.push('-c');
} }
if (disableSearch) { if (commitParent) {
uploadExecArgs.push('--disable-search'); execArgs.push('-N', `${commitParent}`);
} }
if (dryRun) { if (dryRun) {
uploadExecArgs.push('-d'); execArgs.push('-d');
} }
if (envVarsArg.length) { if (envVarsArg.length) {
uploadExecArgs.push('-e', envVarsArg.join(',')); execArgs.push('-e', envVarsArg.join(','));
} }
if (exclude) { if (functionalities) {
uploadExecArgs.push('--exclude', `${exclude}`); functionalities.split(',').map((f) => f.trim()).forEach((f) => {
execArgs.push('-X', `${f}`);
});
} }
if (failCi) { if (failCi) {
uploadExecArgs.push('-Z'); execArgs.push('-Z');
} }
if (file) { if (file) {
uploadExecArgs.push('-f', `${file}`); execArgs.push('-f', `${file}`);
} }
if (files) { if (files) {
files.split(',').map((f) => f.trim()).forEach((f) => { files.split(',').map((f) => f.trim()).forEach((f) => {
uploadExecArgs.push('-f', `${f}`); execArgs.push('-f', `${f}`);
}); });
} }
if (fullReport) {
execArgs.push('--full', `${fullReport}`);
}
if (flags) { if (flags) {
flags.split(',').map((f) => f.trim()).forEach((f) => { flags.split(',').map((f) => f.trim()).forEach((f) => {
uploadExecArgs.push('-F', `${f}`); execArgs.push('-F', `${f}`);
}); });
} }
uploadExecArgs.push('--git-service', `${gitService ? gitService : 'github'}`);
if (handleNoReportsFound) { if (gcov) {
uploadExecArgs.push('--handle-no-reports-found'); execArgs.push('-g');
} }
if (jobCode) { if (gcovArgs) {
uploadExecArgs.push('--job-code', `${jobCode}`); execArgs.push('--ga', `${gcovArgs}`);
} }
if (name) { if (gcovIgnore) {
uploadExecArgs.push('-n', `${name}`); execArgs.push('--gi', `${gcovIgnore}`);
} }
if (gcovInclude) {
execArgs.push('--gI', `${gcovInclude}`);
}
if (gcovExecutable) {
execArgs.push('--gx', `${gcovExecutable}`);
}
if (networkFilter) {
execArgs.push('-i', `${networkFilter}`);
}
if (networkPrefix) {
execArgs.push('-k', `${networkPrefix}`);
}
if (overrideBranch) { if (overrideBranch) {
uploadExecArgs.push('-B', `${overrideBranch}`); execArgs.push('-B', `${overrideBranch}`);
} }
if (overrideBuild) { if (overrideBuild) {
uploadExecArgs.push('-b', `${overrideBuild}`); execArgs.push('-b', `${overrideBuild}`);
}
if (overrideBuildUrl) {
uploadExecArgs.push('--build-url', `${overrideBuildUrl}`);
} }
if (overrideCommit) { if (overrideCommit) {
uploadExecArgs.push('-C', `${overrideCommit}`); execArgs.push('-C', `${overrideCommit}`);
} else if ( } else if (
`${context.eventName}` == 'pull_request' || `${context.eventName}` == 'pull_request' ||
`${context.eventName}` == 'pull_request_target' `${context.eventName}` == 'pull_request_target'
) { ) {
uploadExecArgs.push('-C', `${context.payload.pull_request.head.sha}`); execArgs.push('-C', `${context.payload.pull_request.head.sha}`);
} }
if (overridePr) { if (overridePr) {
uploadExecArgs.push('-P', `${overridePr}`); execArgs.push('-P', `${overridePr}`);
} else if ( } else if (
`${context.eventName}` == 'pull_request_target' `${context.eventName}` == 'pull_request_target'
) { ) {
uploadExecArgs.push('-P', `${context.payload.number}`); execArgs.push('-P', `${context.payload.number}`);
} }
if (plugin) { if (overrideTag) {
uploadExecArgs.push('--plugin', `${plugin}`); execArgs.push('-T', `${overrideTag}`);
}
if (plugins) {
plugins.split(',').map((p) => p.trim()).forEach((p) => {
uploadExecArgs.push('--plugin', `${p}`);
});
}
if (reportCode) {
uploadExecArgs.push('--report-code', `${reportCode}`);
} }
if (rootDir) { if (rootDir) {
uploadExecArgs.push('--network-root-folder', `${rootDir}`); execArgs.push('-R', `${rootDir}`);
} }
if (searchDir) { if (searchDir) {
uploadExecArgs.push('-s', `${searchDir}`); execArgs.push('-s', `${searchDir}`);
} }
if (slug) { if (slug) {
uploadExecArgs.push('-r', `${slug}`); execArgs.push('-r', `${slug}`);
} }
if (workingDir) { if (swift) {
uploadOptions.cwd = workingDir; execArgs.push('--xs');
} }
if (swift && swiftProject) {
execArgs.push('--xsp', `${swiftProject}`);
}
if (upstream) {
execArgs.push('-U', `${upstream}`);
}
if (url) {
execArgs.push('-u', `${url}`);
}
if (verbose) {
execArgs.push('-v');
}
if (xcode && xcodeArchivePath) {
execArgs.push('--xc');
execArgs.push('--xp', `${xcodeArchivePath}`);
}
if (uploaderVersion == '') { if (uploaderVersion == '') {
uploaderVersion = 'latest'; uploaderVersion = 'latest';
} }
if (useLegacyUploadEndpoint) {
uploadExecArgs.push('--legacy'); if (verbose) {
console.debug({execArgs});
} }
return { if (workingDir) {
uploadExecArgs, options.cwd = workingDir;
uploadOptions, }
disableSafeDirectory,
failCi, if (xtraArgs) {
os, execArgs.push(`${xtraArgs}`);
uploaderVersion, }
uploadCommand,
}; return {execArgs, options, failCi, os, uploaderVersion, verbose};
}; };
export default buildExec;
export {
buildCommitExec,
buildGeneralExec,
buildReportExec,
buildUploadExec,
};

View File

@@ -1,13 +1,9 @@
import * as exec from '@actions/exec';
import { import {
PLATFORMS,
getBaseUrl, getBaseUrl,
getCommand,
getPlatform, getPlatform,
isValidPlatform, isValidPlatform,
isWindows, isWindows,
setSafeDirectory, PLATFORMS,
} from './helpers'; } from './helpers';
let OLDOS = process.env.RUNNER_OS; let OLDOS = process.env.RUNNER_OS;
@@ -43,54 +39,34 @@ test('getBaseUrl', () => {
expect(PLATFORMS.map((platform) => { expect(PLATFORMS.map((platform) => {
return getBaseUrl(platform, 'latest'); return getBaseUrl(platform, 'latest');
})).toEqual([ })).toEqual([
'https://cli.codecov.io/latest/linux/codecov', 'https://uploader.codecov.io/latest/aarch64/codecov',
'https://cli.codecov.io/latest/macos/codecov', 'https://uploader.codecov.io/latest/alpine/codecov',
'https://cli.codecov.io/latest/windows/codecov.exe', 'https://uploader.codecov.io/latest/linux/codecov',
'https://cli.codecov.io/latest/alpine/codecov', 'https://uploader.codecov.io/latest/macos/codecov',
'https://cli.codecov.io/latest/linux-arm64/codecov', 'https://uploader.codecov.io/latest/windows/codecov.exe',
'https://cli.codecov.io/latest/alpine-arm64/codecov',
]); ]);
expect(PLATFORMS.map((platform) => { expect(PLATFORMS.map((platform) => {
return getBaseUrl(platform, 'v0.1.0_8880'); return getBaseUrl(platform, 'v0.1.0_8880');
})).toEqual([ })).toEqual([
'https://cli.codecov.io/v0.1.0_8880/linux/codecov', 'https://uploader.codecov.io/v0.1.0_8880/aarch64/codecov',
'https://cli.codecov.io/v0.1.0_8880/macos/codecov', 'https://uploader.codecov.io/v0.1.0_8880/alpine/codecov',
'https://cli.codecov.io/v0.1.0_8880/windows/codecov.exe', 'https://uploader.codecov.io/v0.1.0_8880/linux/codecov',
'https://cli.codecov.io/v0.1.0_8880/alpine/codecov', 'https://uploader.codecov.io/v0.1.0_8880/macos/codecov',
'https://cli.codecov.io/v0.1.0_8880/linux-arm64/codecov', 'https://uploader.codecov.io/v0.1.0_8880/windows/codecov.exe',
'https://cli.codecov.io/v0.1.0_8880/alpine-arm64/codecov',
]); ]);
}); });
test('isWindows', () => { test('isWindows', () => {
expect(PLATFORMS.map((platform) => { expect(PLATFORMS.map((platform) => {
return isWindows(platform); return isWindows(platform);
})).toEqual([false, false, true, false, false, false]); })).toEqual([false, false, false, false, true]);
}); });
test('isValidPlatform', () => { test('isValidPlatform', () => {
expect(PLATFORMS.map((platform) => { expect(PLATFORMS.map((platform) => {
return isValidPlatform(platform); return isValidPlatform(platform);
})).toEqual([true, true, true, true, true, true]); })).toEqual([true, true, true, true, true]);
expect(isValidPlatform('fakeos')).toBeFalsy(); expect(isValidPlatform('fakeos')).toBeFalsy();
}); });
test('getCommand', () => {
expect(getCommand('path', ['-v', '-x'], 'do-upload'))
.toEqual(['path', '-v', '-x', 'do-upload']);
});
test('setSafeDirectory', async () => {
process.env.GITHUB_WORKSPACE = 'testOrg/testRepo';
await setSafeDirectory();
const testSafeDirectory = ([
'git',
'config',
'--get',
'safe.directory',
]).join(' ');
const safeDirectory = await exec.getExecOutput(testSafeDirectory);
expect(safeDirectory.stdout).toBe('testOrg/testRepo\n');
});

View File

@@ -1,13 +1,11 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as exec from '@actions/exec';
const PLATFORMS = [ const PLATFORMS = [
'aarch64',
'alpine',
'linux', 'linux',
'macos', 'macos',
'windows', 'windows',
'alpine',
'linux-arm64',
'alpine-arm64',
]; ];
const setFailure = (message: string, failCi: boolean): void => { const setFailure = (message: string, failCi: boolean): void => {
@@ -52,30 +50,7 @@ const getPlatform = (os?: string): string => {
}; };
const getBaseUrl = (platform: string, version: string): string => { const getBaseUrl = (platform: string, version: string): string => {
return `https://cli.codecov.io/${version}/${platform}/${getUploaderName(platform)}`; return `https://uploader.codecov.io/${version}/${platform}/${getUploaderName(platform)}`;
};
const getCommand = (
filename: string,
generalArgs:string[],
command: string,
): string[] => {
const fullCommand = [filename, ...generalArgs, command];
core.info(`==> Running command '${fullCommand.join(' ')}'`);
return fullCommand;
};
const setSafeDirectory = async () => {
const command = ([
'git',
'config',
'--global',
'--add',
'safe.directory',
`${process.env['GITHUB_WORKSPACE']}`,
].join(' '));
core.info(`==> Running ${command}`);
await exec.exec(command);
}; };
export { export {
@@ -86,6 +61,4 @@ export {
isValidPlatform, isValidPlatform,
isWindows, isWindows,
setFailure, setFailure,
setSafeDirectory,
getCommand,
}; };

View File

@@ -4,19 +4,12 @@ import * as path from 'path';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
import { import buildExec from './buildExec';
buildCommitExec,
buildGeneralExec,
buildReportExec,
buildUploadExec,
} from './buildExec';
import { import {
getBaseUrl, getBaseUrl,
getCommand,
getPlatform, getPlatform,
getUploaderName, getUploaderName,
setFailure, setFailure,
setSafeDirectory,
} from './helpers'; } from './helpers';
import verify from './validate'; import verify from './validate';
@@ -25,19 +18,7 @@ import versionInfo from './version';
let failCi; let failCi;
try { try {
const {commitExecArgs, commitOptions, commitCommand} = buildCommitExec(); const {execArgs, options, failCi, os, uploaderVersion, verbose} = buildExec();
const {reportExecArgs, reportOptions, reportCommand} = buildReportExec();
const {
uploadExecArgs,
uploadOptions,
disableSafeDirectory,
failCi,
os,
uploaderVersion,
uploadCommand,
} = buildUploadExec();
const {args, verbose} = buildGeneralExec();
const platform = getPlatform(os); const platform = getPlatform(os);
const filename = path.join( __dirname, getUploaderName(platform)); const filename = path.join( __dirname, getUploaderName(platform));
@@ -57,9 +38,6 @@ try {
await verify(filename, platform, uploaderVersion, verbose, failCi); await verify(filename, platform, uploaderVersion, verbose, failCi);
await versionInfo(platform, uploaderVersion); await versionInfo(platform, uploaderVersion);
await fs.chmodSync(filename, '777'); await fs.chmodSync(filename, '777');
if (!disableSafeDirectory) {
await setSafeDirectory();
}
const unlink = () => { const unlink = () => {
fs.unlink(filename, (err) => { fs.unlink(filename, (err) => {
@@ -71,52 +49,14 @@ try {
} }
}); });
}; };
const doUpload = async () => { await exec.exec(filename, execArgs, options)
await exec.exec(getCommand(filename, args, uploadCommand).join(' '), .catch((err) => {
uploadExecArgs,
uploadOptions)
.catch((err) => {
setFailure(
`Codecov:
Failed to properly upload report: ${err.message}`,
failCi,
);
});
};
const createReport = async () => {
await exec.exec(
getCommand(filename, args, reportCommand).join(' '),
reportExecArgs,
reportOptions)
.then(async (exitCode) => {
if (exitCode == 0) {
await doUpload();
}
}).catch((err) => {
setFailure(
`Codecov:
Failed to properly create report: ${err.message}`,
failCi,
);
});
};
await exec.exec(
getCommand(
filename,
args,
commitCommand,
).join(' '),
commitExecArgs, commitOptions)
.then(async (exitCode) => {
if (exitCode == 0) {
await createReport();
}
unlink();
}).catch((err) => {
setFailure( setFailure(
`Codecov: Failed to properly create commit: ${err.message}`, `Codecov: Failed to properly upload: ${err.message}`,
failCi, failCi,
); );
}).then(() => {
unlink();
}); });
}); });
}); });

View File

@@ -1,10 +1,10 @@
import * as crypto from 'crypto'; import * as crypto from 'crypto';
import * as fs from 'fs'; import * as fs from 'fs';
import * as gpg from 'gpg';
import * as path from 'path'; import * as path from 'path';
import * as core from '@actions/core'; import * as core from '@actions/core';
import {request} from 'undici'; import * as openpgp from 'openpgp';
import * as fetch from 'node-fetch';
import { import {
getBaseUrl, getBaseUrl,
@@ -22,90 +22,68 @@ const verify = async (
try { try {
const uploaderName = getUploaderName(platform); const uploaderName = getUploaderName(platform);
// Read in public key
const publicKeyArmored = await fs.readFileSync(
path.join(__dirname, 'pgp_keys.asc'),
'utf-8',
);
// Get SHASUM and SHASUM signature files // Get SHASUM and SHASUM signature files
console.log(`${getBaseUrl(platform, version)}.SHA256SUM`); console.log(`${getBaseUrl(platform, version)}.SHA256SUM`);
const shasumRes = await request( const shasumRes = await fetch.default(
`${getBaseUrl(platform, version)}.SHA256SUM`, `${getBaseUrl(platform, version)}.SHA256SUM`,
); );
const shasum = await shasumRes.body.text(); const shasum = await shasumRes.text();
if (verbose) { if (verbose) {
console.log(`Received SHA256SUM ${shasum}`); console.log(`Received SHA256SUM ${shasum}`);
} }
await fs.writeFileSync(
path.join(__dirname, `${uploaderName}.SHA256SUM`),
shasum,
);
const shaSigRes = await request( const shaSigRes = await fetch.default(
`${getBaseUrl(platform, version)}.SHA256SUM.sig`, `${getBaseUrl(platform, version)}.SHA256SUM.sig`,
); );
const shaSig = await shaSigRes.body.text(); const shaSig = await shaSigRes.text();
if (verbose) { if (verbose) {
console.log(`Received SHA256SUM signature ${shaSig}`); console.log(`Received SHA256SUM signature ${shaSig}`);
} }
await fs.writeFileSync(
path.join(__dirname, `${uploaderName}.SHA256SUM.sig`),
shaSig,
);
const validateSha = async () => { // Verify shasum
const calculateHash = async (filename: string) => { const verified = await openpgp.verify({
const stream = fs.createReadStream(filename); message: await openpgp.createMessage({text: shasum}),
const uploaderSha = crypto.createHash(`sha256`); signature: await openpgp.readSignature({armoredSignature: shaSig}),
stream.pipe(uploaderSha); verificationKeys: await openpgp.readKeys({armoredKeys: publicKeyArmored}),
});
return new Promise((resolve, reject) => { const valid = await verified.signatures[0].verified;
stream.on('end', () => resolve( if (valid) {
`${uploaderSha.digest('hex')} ${uploaderName}`, core.info('==> SHASUM file signed by key id ' +
)); verified.signatures[0].keyID.toHex(),
stream.on('error', reject);
});
};
const hash = await calculateHash(
path.join(__dirname, `${uploaderName}`),
); );
if (hash === shasum) { } else {
core.info(`==> Uploader SHASUM verified (${hash})`); setFailure('Codecov: Error validating SHASUM signature', failCi);
} else { }
setFailure(
'Codecov: Uploader shasum does not match -- ' +
`uploader hash: ${hash}, public hash: ${shasum}`,
failCi,
);
}
};
const verifySignature = () => { const calculateHash = async (filename: string) => {
gpg.call('', [ const stream = fs.createReadStream(filename);
'--logger-fd', const uploaderSha = crypto.createHash(`sha256`);
'1', stream.pipe(uploaderSha);
'--verify',
path.join(__dirname, `${uploaderName}.SHA256SUM.sig`), return new Promise((resolve, reject) => {
path.join(__dirname, `${uploaderName}.SHA256SUM`), stream.on('end', () => resolve(
], async (err, verifyResult) => { `${uploaderSha.digest('hex')} ${uploaderName}`,
if (err) { ));
setFailure('Codecov: Error importing pgp key', failCi); stream.on('error', reject);
}
core.info(verifyResult);
await validateSha();
}); });
}; };
// Import gpg key const hash = await calculateHash(filename);
gpg.call('', [ if (hash === shasum) {
'--logger-fd', core.info(`==> Uploader SHASUM verified (${hash})`);
'1', } else {
'--no-default-keyring', setFailure(
'--import', 'Codecov: Uploader shasum does not match -- ' +
path.join(__dirname, 'pgp_keys.asc'), `uploader hash: ${hash}, public hash: ${shasum}`,
], async (err, importResult) => { failCi,
if (err) { );
setFailure('Codecov: Error importing pgp key', failCi); }
}
core.info(importResult);
verifySignature();
});
} catch (err) { } catch (err) {
setFailure(`Codecov: Error validating uploader: ${err.message}`, failCi); setFailure(`Codecov: Error validating uploader: ${err.message}`, failCi);
} }

View File

@@ -1,5 +1,5 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import {request} from 'undici'; import * as fetch from 'node-fetch';
const versionInfo = async ( const versionInfo = async (
platform: string, platform: string,
@@ -10,10 +10,10 @@ const versionInfo = async (
} }
try { try {
const metadataRes = await request(`https://cli.codecov.io/${platform}/latest`, { const metadataRes = await fetch.default( `https://uploader.codecov.io/${platform}/latest`, {
headers: {'Accept': 'application/json'}, headers: {'Accept': 'application/json'},
}); });
const metadata = await metadataRes.body.json(); const metadata = await metadataRes.json();
core.info(`==> Running version ${metadata['version']}`); core.info(`==> Running version ${metadata['version']}`);
} catch (err) { } catch (err) {
core.info(`Could not pull latest version information: ${err}`); core.info(`Could not pull latest version information: ${err}`);