Run prettier on the whole repo
This commit is contained in:
Родитель
d2cb6398a0
Коммит
1d016a2eb6
|
@ -1,72 +1,72 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: "/addon"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- addon
|
||||
- package-ecosystem: pip
|
||||
directory: "/bot"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- bot
|
||||
- package-ecosystem: docker
|
||||
directory: "/events"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- events
|
||||
- package-ecosystem: docker
|
||||
directory: "/backend"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- backend
|
||||
- package-ecosystem: docker
|
||||
directory: "/bot"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- bot
|
||||
- package-ecosystem: pip
|
||||
directory: "/tools"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- tools
|
||||
- package-ecosystem: pip
|
||||
directory: "/events"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- events
|
||||
- package-ecosystem: pip
|
||||
directory: "/backend"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- backend
|
||||
- package-ecosystem: npm
|
||||
directory: "/frontend"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- frontend
|
||||
- package-ecosystem: pip
|
||||
directory: "/report"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- report
|
||||
- package-ecosystem: npm
|
||||
directory: "/addon"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- addon
|
||||
- package-ecosystem: pip
|
||||
directory: "/bot"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- bot
|
||||
- package-ecosystem: docker
|
||||
directory: "/events"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- events
|
||||
- package-ecosystem: docker
|
||||
directory: "/backend"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- backend
|
||||
- package-ecosystem: docker
|
||||
directory: "/bot"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- bot
|
||||
- package-ecosystem: pip
|
||||
directory: "/tools"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- tools
|
||||
- package-ecosystem: pip
|
||||
directory: "/events"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- events
|
||||
- package-ecosystem: pip
|
||||
directory: "/backend"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- backend
|
||||
- package-ecosystem: npm
|
||||
directory: "/frontend"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- frontend
|
||||
- package-ecosystem: pip
|
||||
directory: "/report"
|
||||
schedule:
|
||||
interval: weekly
|
||||
open-pull-requests-limit: 99
|
||||
labels:
|
||||
- report
|
||||
|
|
|
@ -23,7 +23,7 @@ repos:
|
|||
- id: check-yaml
|
||||
- id: mixed-line-ending
|
||||
- id: name-tests-test
|
||||
args: ['--django']
|
||||
args: ["--django"]
|
||||
- id: check-json
|
||||
- id: requirements-txt-fixer
|
||||
- id: check-vcs-permalinks
|
||||
|
@ -44,7 +44,7 @@ repos:
|
|||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.12.1
|
||||
hooks:
|
||||
- id: mypy
|
||||
- id: mypy
|
||||
name: mypy-backend
|
||||
files: ^backend/
|
||||
entry: mypy backend/
|
||||
|
@ -54,7 +54,7 @@ repos:
|
|||
- types-redis==3.5.1
|
||||
- types-python-dateutil==0.1.3
|
||||
- types-PyYAML==5.4.0
|
||||
- id: mypy
|
||||
- id: mypy
|
||||
name: mypy-bot
|
||||
files: ^bot/
|
||||
entry: mypy bot/
|
||||
|
@ -63,21 +63,21 @@ repos:
|
|||
- types-requests==0.1.11
|
||||
- types-pytz==2022.6.0.1
|
||||
- types-PyYAML==5.4.0
|
||||
- id: mypy
|
||||
- id: mypy
|
||||
name: mypy-events
|
||||
files: ^events/
|
||||
entry: mypy events/
|
||||
pass_filenames: false
|
||||
additional_dependencies:
|
||||
- types-requests==0.1.11
|
||||
- id: mypy
|
||||
- id: mypy
|
||||
name: mypy-report
|
||||
files: ^report/
|
||||
entry: mypy report/
|
||||
pass_filenames: false
|
||||
additional_dependencies:
|
||||
- types-requests==0.1.11
|
||||
- id: mypy
|
||||
- id: mypy
|
||||
name: mypy-tools
|
||||
files: ^tools/
|
||||
entry: mypy tools/
|
||||
|
|
153
.taskcluster.yml
153
.taskcluster.yml
|
@ -34,8 +34,8 @@ tasks:
|
|||
then:
|
||||
$if: 'event.ref in ["refs/heads/testing", "refs/heads/production"]'
|
||||
then: ${event.ref[11:]}
|
||||
else: 'dev'
|
||||
else: 'dev'
|
||||
else: "dev"
|
||||
else: "dev"
|
||||
|
||||
channel_short:
|
||||
# Special case where naming is limited:
|
||||
|
@ -44,24 +44,24 @@ tasks:
|
|||
$if: 'tasks_for == "github-push"'
|
||||
then:
|
||||
$if: 'event.ref == "refs/heads/production"'
|
||||
then: 'prod'
|
||||
then: "prod"
|
||||
else: ${event.ref[11:]}
|
||||
else: 'dev'
|
||||
else: "dev"
|
||||
|
||||
backend_url:
|
||||
$if: 'tasks_for == "github-push"'
|
||||
then:
|
||||
$if: 'event.ref == "refs/heads/testing"'
|
||||
then: 'https://api.coverage.testing.moz.tools'
|
||||
else: 'https://api.coverage.moz.tools'
|
||||
else: 'https://api.coverage.moz.tools'
|
||||
then: "https://api.coverage.testing.moz.tools"
|
||||
else: "https://api.coverage.moz.tools"
|
||||
else: "https://api.coverage.moz.tools"
|
||||
|
||||
provisionerId:
|
||||
$if: 'taskcluster_root_url == "https://firefox-ci-tc.services.mozilla.com"'
|
||||
then:
|
||||
$if: 'tasks_for == "github-push"'
|
||||
then: 'code-analysis-3'
|
||||
else: 'code-analysis-1'
|
||||
$if: 'tasks_for == "github-push"'
|
||||
then: "code-analysis-3"
|
||||
else: "code-analysis-1"
|
||||
else: proj-relman
|
||||
|
||||
workerType:
|
||||
|
@ -77,11 +77,11 @@ tasks:
|
|||
$match:
|
||||
# Always run those tasks
|
||||
"true":
|
||||
- taskId: {$eval: as_slugid("check_lint")}
|
||||
- taskId: { $eval: as_slugid("check_lint") }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
payload:
|
||||
maxRunTime: 3600
|
||||
image: python:3.9
|
||||
|
@ -100,11 +100,11 @@ tasks:
|
|||
|
||||
# Run only on firefoxci Taskcluster
|
||||
'taskcluster_root_url == "https://firefox-ci-tc.services.mozilla.com"':
|
||||
- taskId: {$eval: as_slugid("bot_check_tests")}
|
||||
- taskId: { $eval: as_slugid("bot_check_tests") }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
payload:
|
||||
maxRunTime: 3600
|
||||
image: python:3.9
|
||||
|
@ -122,14 +122,14 @@ tasks:
|
|||
owner: bastien@mozilla.com
|
||||
source: https://github.com/mozilla/code-coverage
|
||||
|
||||
- taskId: {$eval: as_slugid("bot_build")}
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
- taskId: { $eval: as_slugid("bot_build") }
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
dependencies:
|
||||
- {$eval: as_slugid("check_lint")}
|
||||
- {$eval: as_slugid("bot_check_tests")}
|
||||
- { $eval: as_slugid("check_lint") }
|
||||
- { $eval: as_slugid("bot_check_tests") }
|
||||
payload:
|
||||
features:
|
||||
dind: true
|
||||
|
@ -152,7 +152,7 @@ tasks:
|
|||
- bot/Dockerfile
|
||||
artifacts:
|
||||
public/code-coverage-bot.tar.zst:
|
||||
expires: {$fromNow: '6 months'}
|
||||
expires: { $fromNow: "6 months" }
|
||||
path: /bot.tar.zst
|
||||
type: file
|
||||
routes:
|
||||
|
@ -169,14 +169,13 @@ tasks:
|
|||
owner: bastien@mozilla.com
|
||||
source: https://github.com/mozilla/code-coverage
|
||||
|
||||
|
||||
# Run only on community Taskcluster
|
||||
'taskcluster_root_url == "https://community-tc.services.mozilla.com"':
|
||||
- taskId: {$eval: as_slugid("backend_check_tests")}
|
||||
- taskId: { $eval: as_slugid("backend_check_tests") }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
payload:
|
||||
maxRunTime: 3600
|
||||
image: python:3.9
|
||||
|
@ -193,11 +192,11 @@ tasks:
|
|||
owner: bastien@mozilla.com
|
||||
source: https://github.com/mozilla/code-coverage
|
||||
|
||||
- taskId: {$eval: as_slugid("events_check_tests")}
|
||||
- taskId: { $eval: as_slugid("events_check_tests") }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
payload:
|
||||
maxRunTime: 3600
|
||||
image: python:3.9
|
||||
|
@ -213,11 +212,11 @@ tasks:
|
|||
owner: bastien@mozilla.com
|
||||
source: https://github.com/mozilla/code-coverage
|
||||
|
||||
- taskId: {$eval: as_slugid("report_check_tests")}
|
||||
- taskId: { $eval: as_slugid("report_check_tests") }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
payload:
|
||||
features:
|
||||
taskclusterProxy: true
|
||||
|
@ -234,14 +233,14 @@ tasks:
|
|||
owner: bastien@mozilla.com
|
||||
source: https://github.com/mozilla/code-coverage
|
||||
|
||||
- taskId: {$eval: as_slugid("backend_build")}
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
- taskId: { $eval: as_slugid("backend_build") }
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
dependencies:
|
||||
- {$eval: as_slugid("check_lint")}
|
||||
- {$eval: as_slugid("backend_check_tests")}
|
||||
- { $eval: as_slugid("check_lint") }
|
||||
- { $eval: as_slugid("backend_check_tests") }
|
||||
payload:
|
||||
capabilities:
|
||||
privileged: true
|
||||
|
@ -264,7 +263,7 @@ tasks:
|
|||
- backend/Dockerfile
|
||||
artifacts:
|
||||
public/code-coverage-backend.tar.zst:
|
||||
expires: {$fromNow: '2 weeks'}
|
||||
expires: { $fromNow: "2 weeks" }
|
||||
path: /backend.tar.zst
|
||||
type: file
|
||||
scopes:
|
||||
|
@ -275,14 +274,14 @@ tasks:
|
|||
owner: bastien@mozilla.com
|
||||
source: https://github.com/mozilla/code-coverage
|
||||
|
||||
- taskId: {$eval: as_slugid("events_build")}
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
- taskId: { $eval: as_slugid("events_build") }
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
dependencies:
|
||||
- {$eval: as_slugid("check_lint")}
|
||||
- {$eval: as_slugid("events_check_tests")}
|
||||
- { $eval: as_slugid("check_lint") }
|
||||
- { $eval: as_slugid("events_check_tests") }
|
||||
payload:
|
||||
capabilities:
|
||||
privileged: true
|
||||
|
@ -305,7 +304,7 @@ tasks:
|
|||
- events/Dockerfile
|
||||
artifacts:
|
||||
public/code-coverage-events.tar.zst:
|
||||
expires: {$fromNow: '2 weeks'}
|
||||
expires: { $fromNow: "2 weeks" }
|
||||
path: /events.tar.zst
|
||||
type: file
|
||||
scopes:
|
||||
|
@ -316,11 +315,11 @@ tasks:
|
|||
owner: bastien@mozilla.com
|
||||
source: https://github.com/mozilla/code-coverage
|
||||
|
||||
- taskId: {$eval: as_slugid("addon_build")}
|
||||
- taskId: { $eval: as_slugid("addon_build") }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
payload:
|
||||
maxRunTime: 3600
|
||||
image: node:20-alpine
|
||||
|
@ -335,7 +334,7 @@ tasks:
|
|||
npm run export"
|
||||
artifacts:
|
||||
public/addon:
|
||||
expires: {$fromNow: '2 weeks'}
|
||||
expires: { $fromNow: "2 weeks" }
|
||||
path: /src/addon/web-ext-artifacts
|
||||
type: directory
|
||||
metadata:
|
||||
|
@ -344,11 +343,11 @@ tasks:
|
|||
owner: bastien@mozilla.com
|
||||
source: https://github.com/mozilla/code-coverage
|
||||
|
||||
- taskId: {$eval: as_slugid("frontend_build")}
|
||||
- taskId: { $eval: as_slugid("frontend_build") }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
payload:
|
||||
maxRunTime: 3600
|
||||
image: node:20
|
||||
|
@ -361,7 +360,7 @@ tasks:
|
|||
npm install --no-progress && npm run release"
|
||||
artifacts:
|
||||
public/frontend:
|
||||
expires: {$fromNow: '2 weeks'}
|
||||
expires: { $fromNow: "2 weeks" }
|
||||
path: /src/frontend/dist
|
||||
type: directory
|
||||
metadata:
|
||||
|
@ -372,13 +371,13 @@ tasks:
|
|||
|
||||
- $if: 'channel in ["testing", "production"]'
|
||||
then:
|
||||
taskId: {$eval: as_slugid("backend_deploy")}
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
taskId: { $eval: as_slugid("backend_deploy") }
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
dependencies:
|
||||
- {$eval: as_slugid("backend_build")}
|
||||
- { $eval: as_slugid("backend_build") }
|
||||
payload:
|
||||
features:
|
||||
taskclusterProxy: true
|
||||
|
@ -402,13 +401,13 @@ tasks:
|
|||
|
||||
- $if: 'channel in ["testing", "production"]'
|
||||
then:
|
||||
taskId: {$eval: as_slugid("events_deploy")}
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
taskId: { $eval: as_slugid("events_deploy") }
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
dependencies:
|
||||
- {$eval: as_slugid("events_build")}
|
||||
- { $eval: as_slugid("events_build") }
|
||||
payload:
|
||||
features:
|
||||
taskclusterProxy: true
|
||||
|
@ -432,13 +431,13 @@ tasks:
|
|||
|
||||
- $if: 'channel in ["testing", "production"]'
|
||||
then:
|
||||
taskId: {$eval: as_slugid("frontend_deploy")}
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
taskId: { $eval: as_slugid("frontend_deploy") }
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
dependencies:
|
||||
- {$eval: as_slugid("frontend_build")}
|
||||
- { $eval: as_slugid("frontend_build") }
|
||||
payload:
|
||||
features:
|
||||
# Needed for access to secret
|
||||
|
@ -465,18 +464,18 @@ tasks:
|
|||
- $if: 'tasks_for == "github-push" && head_branch[:10] == "refs/tags/"'
|
||||
then:
|
||||
$let:
|
||||
version: {$eval: 'head_branch[10:]'}
|
||||
version: { $eval: "head_branch[10:]" }
|
||||
in:
|
||||
taskId: {$eval: as_slugid("release")}
|
||||
taskId: { $eval: as_slugid("release") }
|
||||
dependencies:
|
||||
- {$eval: as_slugid("addon_build")}
|
||||
- {$eval: as_slugid("backend_build")}
|
||||
- {$eval: as_slugid("frontend_build")}
|
||||
- {$eval: as_slugid("report_check_tests")}
|
||||
- { $eval: as_slugid("addon_build") }
|
||||
- { $eval: as_slugid("backend_build") }
|
||||
- { $eval: as_slugid("frontend_build") }
|
||||
- { $eval: as_slugid("report_check_tests") }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
payload:
|
||||
features:
|
||||
# Needed for access to secret
|
||||
|
@ -500,13 +499,13 @@ tasks:
|
|||
|
||||
- $if: 'tasks_for == "github-push" && head_branch[:10] == "refs/tags/"'
|
||||
then:
|
||||
taskId: {$eval: as_slugid("report_deploy_pypi")}
|
||||
taskId: { $eval: as_slugid("report_deploy_pypi") }
|
||||
dependencies:
|
||||
- {$eval: as_slugid("report_check_tests")}
|
||||
- { $eval: as_slugid("report_check_tests") }
|
||||
provisionerId: "${provisionerId}"
|
||||
workerType: "${workerType}"
|
||||
created: {$fromNow: ''}
|
||||
deadline: {$fromNow: '1 hour'}
|
||||
created: { $fromNow: "" }
|
||||
deadline: { $fromNow: "1 hour" }
|
||||
payload:
|
||||
features:
|
||||
# Needed for access to secret
|
||||
|
@ -521,7 +520,7 @@ tasks:
|
|||
- "git clone ${repository} /project && cd /project && git checkout ${head_rev} -b release &&
|
||||
taskboot --target=/project/report deploy-pypi"
|
||||
scopes:
|
||||
- "secrets:get:project/relman/code-coverage/release"
|
||||
- "secrets:get:project/relman/code-coverage/release"
|
||||
metadata:
|
||||
name: "Code Coverage Report: publish on pypi"
|
||||
description: Code Coverage Github Pypi publication for report
|
||||
|
|
|
@ -5,4 +5,5 @@ For more details, please read the
|
|||
[Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/).
|
||||
|
||||
## How to Report
|
||||
|
||||
For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page.
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
This project has 4 parts:
|
||||
|
||||
* `bot` is a Python script running as a Taskcluster hook, aggregating code coverage data from Mozilla repositories,
|
||||
* `backend` is a Python API built with Flask, that serves the aggregated code coverage data, in an efficient way,
|
||||
* `frontend` is a vanilla Javascript SPA displaying code coverage data in your browser,
|
||||
* `addon` is a Web Extension for Firefox, extending several Mozilla websites with code coverage data. Published at https://addons.mozilla.org/firefox/addon/gecko-code-coverage/.
|
||||
- `bot` is a Python script running as a Taskcluster hook, aggregating code coverage data from Mozilla repositories,
|
||||
- `backend` is a Python API built with Flask, that serves the aggregated code coverage data, in an efficient way,
|
||||
- `frontend` is a vanilla Javascript SPA displaying code coverage data in your browser,
|
||||
- `addon` is a Web Extension for Firefox, extending several Mozilla websites with code coverage data. Published at https://addons.mozilla.org/firefox/addon/gecko-code-coverage/.
|
||||
|
||||
## Help
|
||||
|
||||
|
|
|
@ -1,35 +1,26 @@
|
|||
module.exports = {
|
||||
"globals": {
|
||||
globals: {},
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
webextensions: true,
|
||||
},
|
||||
plugins: ["mozilla"],
|
||||
extends: ["plugin:mozilla/recommended", "eslint:recommended"],
|
||||
parserOptions: {
|
||||
ecmaVersion: 8,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true,
|
||||
"webextensions": true
|
||||
},
|
||||
"plugins": [
|
||||
"mozilla"
|
||||
sourceType: "module",
|
||||
},
|
||||
rules: {
|
||||
indent: ["error", 2],
|
||||
"no-console": [
|
||||
"error",
|
||||
{
|
||||
allow: ["error"],
|
||||
},
|
||||
],
|
||||
"extends": [
|
||||
"plugin:mozilla/recommended",
|
||||
"eslint:recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 8,
|
||||
"ecmaFeatures": {
|
||||
"jsx": true
|
||||
},
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
2
|
||||
],
|
||||
"no-console": [
|
||||
"error",
|
||||
{
|
||||
"allow": ["error"]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -4,4 +4,4 @@
|
|||
|
||||
Extension that augments several Mozilla websites (DXR, Searchfox) with code coverage information.
|
||||
|
||||
The extension can be found at https://addons.mozilla.org/firefox/addon/gecko-code-coverage/.
|
||||
The extension can be found at https://addons.mozilla.org/firefox/addon/gecko-code-coverage/.
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
[
|
||||
"c",
|
||||
"h",
|
||||
"cpp",
|
||||
"cc",
|
||||
"cxx",
|
||||
"hh",
|
||||
"hpp",
|
||||
"hxx",
|
||||
"js",
|
||||
"jsm",
|
||||
"mjs",
|
||||
"jsx",
|
||||
"xul",
|
||||
"xml",
|
||||
"html",
|
||||
"xhtml"
|
||||
"c",
|
||||
"h",
|
||||
"cpp",
|
||||
"cc",
|
||||
"cxx",
|
||||
"hh",
|
||||
"hpp",
|
||||
"hxx",
|
||||
"js",
|
||||
"jsm",
|
||||
"mjs",
|
||||
"jsx",
|
||||
"xul",
|
||||
"xml",
|
||||
"html",
|
||||
"xhtml"
|
||||
]
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
"run_at": "document_end"
|
||||
},
|
||||
{
|
||||
"matches": ["*://hg.mozilla.org/mozilla-central/file/*",
|
||||
"*://hg.mozilla.org/mozilla-central/annotate/*"],
|
||||
"matches": [
|
||||
"*://hg.mozilla.org/mozilla-central/file/*",
|
||||
"*://hg.mozilla.org/mozilla-central/annotate/*"
|
||||
],
|
||||
"js": ["build/hgmo.js"],
|
||||
"css": ["src/spinner.css", "src/dxr.css"],
|
||||
"run_at": "document_end"
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
import {fetchCoverage} from './coverage';
|
||||
import { fetchCoverage } from "./coverage";
|
||||
|
||||
let resultPromise;
|
||||
export async function getCoverage(revPromise, path) {
|
||||
if (!resultPromise) {
|
||||
resultPromise = (async function() {
|
||||
resultPromise = (async function () {
|
||||
const rev = await revPromise;
|
||||
return fetchCoverage(rev, path);
|
||||
})();
|
||||
|
@ -19,8 +19,8 @@ export async function getCoverage(revPromise, path) {
|
|||
}
|
||||
|
||||
function disableButton(button, text) {
|
||||
button.setAttribute('disabled', 'disabled');
|
||||
button.style['cursor'] = 'not-allowed';
|
||||
button.setAttribute("disabled", "disabled");
|
||||
button.style["cursor"] = "not-allowed";
|
||||
button.title = text;
|
||||
}
|
||||
|
||||
|
@ -28,13 +28,13 @@ export function injectToggle(revPromise, path, applyOverlay, removeOverlay) {
|
|||
// Preload coverage data.
|
||||
getCoverage(revPromise, path);
|
||||
|
||||
const spinner = document.createElement('div');
|
||||
spinner.classList.add('gecko_coverage_loader', 'gecko_coverage_loader_dxr');
|
||||
const spinner = document.createElement("div");
|
||||
spinner.classList.add("gecko_coverage_loader", "gecko_coverage_loader_dxr");
|
||||
|
||||
let button = document.createElement('button');
|
||||
button.type = 'button';
|
||||
button.textContent = 'Code Coverage ';
|
||||
button.className = 'gecko_code_coverage_toggle_button';
|
||||
let button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.textContent = "Code Coverage ";
|
||||
button.className = "gecko_code_coverage_toggle_button";
|
||||
|
||||
let enabled = false;
|
||||
async function toggle() {
|
||||
|
@ -43,16 +43,19 @@ export function injectToggle(revPromise, path, applyOverlay, removeOverlay) {
|
|||
button.appendChild(spinner);
|
||||
try {
|
||||
await applyOverlay(revPromise, path);
|
||||
button.style.backgroundColor = 'lightgrey';
|
||||
button.style.backgroundColor = "lightgrey";
|
||||
} catch (ex) {
|
||||
button.style.backgroundColor = 'red';
|
||||
disableButton(button, 'Error retrieving coverage information for this file');
|
||||
button.style.backgroundColor = "red";
|
||||
disableButton(
|
||||
button,
|
||||
"Error retrieving coverage information for this file",
|
||||
);
|
||||
} finally {
|
||||
button.removeChild(spinner);
|
||||
}
|
||||
} else {
|
||||
removeOverlay();
|
||||
button.style.backgroundColor = 'white';
|
||||
button.style.backgroundColor = "white";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
export const BACKEND_URL = 'https://api.coverage.moz.tools';
|
||||
export const BACKEND_URL = "https://api.coverage.moz.tools";
|
||||
|
|
|
@ -2,25 +2,29 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
import {BACKEND_URL} from './config';
|
||||
const extensions = require('extensions.json')
|
||||
import { BACKEND_URL } from "./config";
|
||||
const extensions = require("extensions.json");
|
||||
|
||||
export async function fetchCoverage(rev, path) {
|
||||
let response = await fetch(`${BACKEND_URL}/v2/path?path=${path}&changeset=${rev}`);
|
||||
let response = await fetch(
|
||||
`${BACKEND_URL}/v2/path?path=${path}&changeset=${rev}`,
|
||||
);
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
export async function gitToHg(gitrev) {
|
||||
let response = await fetch(`https://mapper.mozilla-releng.net/gecko-dev/rev/git/${gitrev}`);
|
||||
let response = await fetch(
|
||||
`https://mapper.mozilla-releng.net/gecko-dev/rev/git/${gitrev}`,
|
||||
);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error retrieving git to mercurial mapping for ${gitrev}.`);
|
||||
}
|
||||
let text = await response.text();
|
||||
return text.split(' ')[1];
|
||||
return text.split(" ")[1];
|
||||
}
|
||||
|
||||
export function isCoverageSupported(path) {
|
||||
return extensions.findIndex(ext => path.endsWith(`.${ext}`)) != -1;
|
||||
return extensions.findIndex((ext) => path.endsWith(`.${ext}`)) != -1;
|
||||
}
|
||||
|
|
|
@ -2,21 +2,21 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
import {getCoverage} from './button';
|
||||
import { getCoverage } from "./button";
|
||||
|
||||
let lineNoMap = (function() {
|
||||
let lineNoMap = (function () {
|
||||
let mapper;
|
||||
|
||||
return function(l) {
|
||||
return function (l) {
|
||||
if (!mapper) {
|
||||
if (document.getElementById('l1')) {
|
||||
mapper = l => `l${l}`;
|
||||
} else if (document.getElementById('1')) {
|
||||
mapper = l => l;
|
||||
if (document.getElementById("l1")) {
|
||||
mapper = (l) => `l${l}`;
|
||||
} else if (document.getElementById("1")) {
|
||||
mapper = (l) => l;
|
||||
} else {
|
||||
throw new Error('Unknown line number element.');
|
||||
throw new Error("Unknown line number element.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,19 +27,19 @@ let lineNoMap = (function() {
|
|||
export async function applyOverlay(revPromise, path) {
|
||||
let result = await getCoverage(revPromise, path);
|
||||
|
||||
if (!result.hasOwnProperty('coverage')) {
|
||||
throw new Error('No \'coverage\' field');
|
||||
if (!result.hasOwnProperty("coverage")) {
|
||||
throw new Error("No 'coverage' field");
|
||||
}
|
||||
for (var l in result.coverage) {
|
||||
l = parseInt(l) + 1;
|
||||
const line_no = document.getElementById(lineNoMap(l));
|
||||
const line = document.getElementById(`line-${l}`);
|
||||
if (result.coverage[l] > 0) {
|
||||
line_no.style.backgroundColor = 'greenyellow';
|
||||
line.style.backgroundColor = 'greenyellow';
|
||||
line_no.style.backgroundColor = "greenyellow";
|
||||
line.style.backgroundColor = "greenyellow";
|
||||
} else {
|
||||
line_no.style.backgroundColor = 'tomato';
|
||||
line.style.backgroundColor = 'tomato';
|
||||
line_no.style.backgroundColor = "tomato";
|
||||
line.style.backgroundColor = "tomato";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,8 +54,8 @@ export function removeOverlay() {
|
|||
}
|
||||
const line = document.getElementById(`line-${l}`);
|
||||
|
||||
line_no.style.backgroundColor = '';
|
||||
line.style.backgroundColor = '';
|
||||
line_no.style.backgroundColor = "";
|
||||
line.style.backgroundColor = "";
|
||||
|
||||
l += 1;
|
||||
}
|
||||
|
@ -63,14 +63,14 @@ export function removeOverlay() {
|
|||
|
||||
// Get the currently open file path.
|
||||
export function getPath() {
|
||||
const breadcrumbs = document.querySelector('.breadcrumbs');
|
||||
const breadcrumbs = document.querySelector(".breadcrumbs");
|
||||
if (!breadcrumbs) {
|
||||
return;
|
||||
}
|
||||
|
||||
return breadcrumbs.lastElementChild.href.split('/mozilla-central/source/')[1];
|
||||
return breadcrumbs.lastElementChild.href.split("/mozilla-central/source/")[1];
|
||||
}
|
||||
|
||||
export function getNavigationPanel() {
|
||||
return document.getElementById('panel-content');
|
||||
return document.getElementById("panel-content");
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
.gecko_code_coverage_toggle_button {
|
||||
background-color: white;
|
||||
margin-bottom: .2rem;
|
||||
margin-right: .2rem;
|
||||
padding: .3rem;
|
||||
margin-bottom: 0.2rem;
|
||||
margin-right: 0.2rem;
|
||||
padding: 0.3rem;
|
||||
border: 1px solid #999;
|
||||
width: auto;
|
||||
min-width: 100px;
|
||||
border-radius: .2rem;
|
||||
border-radius: 0.2rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
@ -2,13 +2,18 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
import {injectToggle} from './button';
|
||||
import {isCoverageSupported} from './coverage';
|
||||
import {applyOverlay, removeOverlay, getPath, getNavigationPanel} from './dxr-common';
|
||||
import { injectToggle } from "./button";
|
||||
import { isCoverageSupported } from "./coverage";
|
||||
import {
|
||||
applyOverlay,
|
||||
removeOverlay,
|
||||
getPath,
|
||||
getNavigationPanel,
|
||||
} from "./dxr-common";
|
||||
|
||||
(function() {
|
||||
(function () {
|
||||
// Don't do anything if this isn't a file.
|
||||
const panel = getNavigationPanel();
|
||||
if (!panel) {
|
||||
|
@ -21,7 +26,7 @@ import {applyOverlay, removeOverlay, getPath, getNavigationPanel} from './dxr-co
|
|||
}
|
||||
|
||||
// Get the current revision.
|
||||
const revPattern = new RegExp('Mercurial \\(([0-9a-f]+)\\)');
|
||||
const revPattern = new RegExp("Mercurial \\(([0-9a-f]+)\\)");
|
||||
const m = panel.innerHTML.match(revPattern);
|
||||
const revPromise = Promise.resolve(m[1]);
|
||||
|
||||
|
@ -30,6 +35,6 @@ import {applyOverlay, removeOverlay, getPath, getNavigationPanel} from './dxr-co
|
|||
return;
|
||||
}
|
||||
|
||||
let treeSelector = document.getElementById('tree-selector');
|
||||
let treeSelector = document.getElementById("tree-selector");
|
||||
treeSelector.appendChild(button);
|
||||
})();
|
||||
|
|
|
@ -4,14 +4,16 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
import {getCoverage, injectToggle} from './button';
|
||||
import { getCoverage, injectToggle } from "./button";
|
||||
|
||||
let filename = "";
|
||||
let revision = "";
|
||||
const linePattern = new RegExp("^l([0-9]+)$");
|
||||
|
||||
document.querySelectorAll("title").forEach(title => {
|
||||
const titlePattern = new RegExp("^mozilla-central: ([^@]+)@([0-9a-f]+)(?: \\(annotated\\))?$");
|
||||
document.querySelectorAll("title").forEach((title) => {
|
||||
const titlePattern = new RegExp(
|
||||
"^mozilla-central: ([^@]+)@([0-9a-f]+)(?: \\(annotated\\))?$",
|
||||
);
|
||||
const m = title.innerText.match(titlePattern);
|
||||
if (m) {
|
||||
filename = m[1];
|
||||
|
@ -25,20 +27,20 @@ async function applyOverlay(revPromise, path) {
|
|||
throw new Error("No 'coverage' field");
|
||||
}
|
||||
const data = result["coverage"];
|
||||
document.querySelectorAll("[id^='l']").forEach(e => {
|
||||
document.querySelectorAll("[id^='l']").forEach((e) => {
|
||||
const m = e.id.match(linePattern);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
const linenum = m[1];
|
||||
if (data.hasOwnProperty(linenum)) {
|
||||
e.style.backgroundColor = (data[linenum] > 0) ? "greenyellow" : "tomato";
|
||||
e.style.backgroundColor = data[linenum] > 0 ? "greenyellow" : "tomato";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function removeOverlay() {
|
||||
document.querySelectorAll("[id^='l']").forEach(e => {
|
||||
document.querySelectorAll("[id^='l']").forEach((e) => {
|
||||
const m = e.id.match(linePattern);
|
||||
if (m) {
|
||||
e.style.backgroundColor = "";
|
||||
|
|
|
@ -2,13 +2,18 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
import {injectToggle} from './button';
|
||||
import {gitToHg, isCoverageSupported} from './coverage';
|
||||
import {applyOverlay, removeOverlay, getPath, getNavigationPanel} from './dxr-common';
|
||||
import { injectToggle } from "./button";
|
||||
import { gitToHg, isCoverageSupported } from "./coverage";
|
||||
import {
|
||||
applyOverlay,
|
||||
removeOverlay,
|
||||
getPath,
|
||||
getNavigationPanel,
|
||||
} from "./dxr-common";
|
||||
|
||||
(async function() {
|
||||
(async function () {
|
||||
// Don't do anything if this isn't a file.
|
||||
if (!getNavigationPanel()) {
|
||||
return;
|
||||
|
@ -21,7 +26,7 @@ import {applyOverlay, removeOverlay, getPath, getNavigationPanel} from './dxr-co
|
|||
|
||||
// Get the current revision.
|
||||
const revPattern = new RegExp('/mozilla-central/commit/([0-9a-f]+)"');
|
||||
const revSpan = document.getElementById('rev-id');
|
||||
const revSpan = document.getElementById("rev-id");
|
||||
const m = revSpan.innerHTML.match(revPattern);
|
||||
const gitRev = m[1];
|
||||
const revPromise = gitToHg(gitRev);
|
||||
|
@ -31,7 +36,7 @@ import {applyOverlay, removeOverlay, getPath, getNavigationPanel} from './dxr-co
|
|||
return;
|
||||
}
|
||||
|
||||
const breadcrumbs = document.querySelector('.breadcrumbs');
|
||||
const breadcrumbs = document.querySelector(".breadcrumbs");
|
||||
if (!breadcrumbs) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.codecov-icon {
|
||||
background: url("codecov.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: auto 1.3em;
|
||||
width: 1.3em;
|
||||
height: 1.3em;
|
||||
display: inline-block;
|
||||
background: url("codecov.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: auto 1.3em;
|
||||
width: 1.3em;
|
||||
height: 1.3em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
|
|
@ -4,45 +4,55 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
import {isCoverageSupported, fetchCoverage} from './coverage';
|
||||
import { isCoverageSupported, fetchCoverage } from "./coverage";
|
||||
|
||||
const hgurlPattern = new RegExp("^http[s]?://hg\\.mozilla\\.org/mozilla-central/annotate/([0-9a-f]+)/([^#]+)#l([0-9]+)$");
|
||||
const hgurlPattern = new RegExp(
|
||||
"^http[s]?://hg\\.mozilla\\.org/mozilla-central/annotate/([0-9a-f]+)/([^#]+)#l([0-9]+)$",
|
||||
);
|
||||
// fileinfo: filename => { revision => [{line, element}, ...] }
|
||||
const fileinfo = {};
|
||||
document.querySelectorAll("#frames table:first-of-type td > a[href^='https://hg.mozilla.org/mozilla-central/annotate/']").forEach(a => {
|
||||
const m = a.href.match(hgurlPattern);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
const filename = m[2];
|
||||
if (!isCoverageSupported(filename)) {
|
||||
return;
|
||||
}
|
||||
const line = m[3];
|
||||
if (line === "0") { // shouldn't happen... but irl it happens
|
||||
return;
|
||||
}
|
||||
const revision = m[1].slice(0, 12); // shorten the revision
|
||||
const info = {
|
||||
"line": line,
|
||||
"element": a.parentNode
|
||||
};
|
||||
let finfo;
|
||||
if (filename in fileinfo) {
|
||||
finfo = fileinfo[filename];
|
||||
} else {
|
||||
finfo = fileinfo[filename] = {};
|
||||
}
|
||||
if (revision in finfo) {
|
||||
finfo[revision].push(info);
|
||||
} else {
|
||||
finfo[revision] = [info];
|
||||
}
|
||||
});
|
||||
document
|
||||
.querySelectorAll(
|
||||
"#frames table:first-of-type td > a[href^='https://hg.mozilla.org/mozilla-central/annotate/']",
|
||||
)
|
||||
.forEach((a) => {
|
||||
const m = a.href.match(hgurlPattern);
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
const filename = m[2];
|
||||
if (!isCoverageSupported(filename)) {
|
||||
return;
|
||||
}
|
||||
const line = m[3];
|
||||
if (line === "0") {
|
||||
// shouldn't happen... but irl it happens
|
||||
return;
|
||||
}
|
||||
const revision = m[1].slice(0, 12); // shorten the revision
|
||||
const info = {
|
||||
line: line,
|
||||
element: a.parentNode,
|
||||
};
|
||||
let finfo;
|
||||
if (filename in fileinfo) {
|
||||
finfo = fileinfo[filename];
|
||||
} else {
|
||||
finfo = fileinfo[filename] = {};
|
||||
}
|
||||
if (revision in finfo) {
|
||||
finfo[revision].push(info);
|
||||
} else {
|
||||
finfo[revision] = [info];
|
||||
}
|
||||
});
|
||||
|
||||
if (Object.keys(fileinfo).length != 0) {
|
||||
const spinnerDiv = document.createElement("div");
|
||||
spinnerDiv.classList.add("gecko_coverage_loader", "gecko_coverage_loader_socorro");
|
||||
spinnerDiv.classList.add(
|
||||
"gecko_coverage_loader",
|
||||
"gecko_coverage_loader_socorro",
|
||||
);
|
||||
spinnerDiv.style.display = "inline-block";
|
||||
|
||||
const linkToCodecov = document.createElement("a");
|
||||
|
@ -59,31 +69,34 @@ if (Object.keys(fileinfo).length != 0) {
|
|||
le.element.append(e);
|
||||
le.element = e;
|
||||
}
|
||||
fetchCoverage(revision, filename).then(data => {
|
||||
if (data !== null && !data.hasOwnProperty("error")) {
|
||||
if (!data.hasOwnProperty("coverage")) {
|
||||
throw new Error("No 'data' field");
|
||||
}
|
||||
const covData = data["coverage"];
|
||||
for (const le of lineElements) {
|
||||
const line = le.line;
|
||||
if (line in covData) {
|
||||
// line is covered or uncovered
|
||||
le.element.parentNode.style.backgroundColor = covData[line] == 0 ? "tomato" : "greenyellow";
|
||||
const gitBuildChangeset = data["git_build_changeset"];
|
||||
const codecovUrl = `https://codecov.io/gh/mozilla/gecko-dev/src/${gitBuildChangeset}/${filename}#L${line}`;
|
||||
const a = linkToCodecov.cloneNode(true);
|
||||
a.setAttribute("href", codecovUrl);
|
||||
le.element.parentNode.append(a);
|
||||
fetchCoverage(revision, filename)
|
||||
.then((data) => {
|
||||
if (data !== null && !data.hasOwnProperty("error")) {
|
||||
if (!data.hasOwnProperty("coverage")) {
|
||||
throw new Error("No 'data' field");
|
||||
}
|
||||
const covData = data["coverage"];
|
||||
for (const le of lineElements) {
|
||||
const line = le.line;
|
||||
if (line in covData) {
|
||||
// line is covered or uncovered
|
||||
le.element.parentNode.style.backgroundColor =
|
||||
covData[line] == 0 ? "tomato" : "greenyellow";
|
||||
const gitBuildChangeset = data["git_build_changeset"];
|
||||
const codecovUrl = `https://codecov.io/gh/mozilla/gecko-dev/src/${gitBuildChangeset}/${filename}#L${line}`;
|
||||
const a = linkToCodecov.cloneNode(true);
|
||||
a.setAttribute("href", codecovUrl);
|
||||
le.element.parentNode.append(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).finally(() => {
|
||||
// Remove the spinners
|
||||
for (const le of lineElements) {
|
||||
le.element.remove();
|
||||
}
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
// Remove the spinners
|
||||
for (const le of lineElements) {
|
||||
le.element.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
@keyframes gecko_coverage_loader_spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.gecko_coverage_loader {
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
mode: "development",
|
||||
entry: {
|
||||
'dxr': './src/dxr.js',
|
||||
'searchfox': './src/searchfox.js',
|
||||
'socorro': './src/socorro.js',
|
||||
'hgmo': './src/hgmo.js',
|
||||
dxr: "./src/dxr.js",
|
||||
searchfox: "./src/searchfox.js",
|
||||
socorro: "./src/socorro.js",
|
||||
hgmo: "./src/hgmo.js",
|
||||
},
|
||||
plugins: [
|
||||
// Since some NodeJS modules expect to be running in Node, it is helpful
|
||||
// to set this environment var to avoid reference errors.
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||
"process.env.NODE_ENV": JSON.stringify("production"),
|
||||
}),
|
||||
],
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'build'),
|
||||
filename: '[name].js'
|
||||
path: path.resolve(__dirname, "build"),
|
||||
filename: "[name].js",
|
||||
},
|
||||
resolve : {
|
||||
modules : ['src', 'assets'],
|
||||
resolve: {
|
||||
modules: ["src", "assets"],
|
||||
},
|
||||
|
||||
// This will expose source map files so that errors will point to your
|
||||
// original source files instead of the transpiled files.
|
||||
devtool: 'source-map',
|
||||
devtool: "source-map",
|
||||
};
|
||||
|
|
|
@ -6,11 +6,10 @@ The production instance of this service is hosted on https://api.coverage.moz.to
|
|||
|
||||
We currently have several endpoints implemented:
|
||||
|
||||
* `/v2/extensions` lists all the file extensions supported by the code coverage suite,
|
||||
* `/v2/latest` lists the 10 latest code coverage reports ingested on the backend and available to query,
|
||||
* `/v2/history` shows the code coverage progression for a specific path in a repository,
|
||||
* `/v2/path` provides the code coverage information for a directory or file in a repository, at a given revision.
|
||||
|
||||
- `/v2/extensions` lists all the file extensions supported by the code coverage suite,
|
||||
- `/v2/latest` lists the 10 latest code coverage reports ingested on the backend and available to query,
|
||||
- `/v2/history` shows the code coverage progression for a specific path in a repository,
|
||||
- `/v2/path` provides the code coverage information for a directory or file in a repository, at a given revision.
|
||||
|
||||
## Setup instructions for developers
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@ paths:
|
|||
get:
|
||||
operationId: "code_coverage_backend.api.coverage_latest"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: query
|
||||
description: Mozilla repository for these reports (default to mozilla-central)
|
||||
required: false
|
||||
type: string
|
||||
- name: repository
|
||||
in: query
|
||||
description: Mozilla repository for these reports (default to mozilla-central)
|
||||
required: false
|
||||
type: string
|
||||
responses:
|
||||
200:
|
||||
description: Latest coverage builds
|
||||
|
@ -27,31 +27,31 @@ paths:
|
|||
get:
|
||||
operationId: "code_coverage_backend.api.coverage_for_path"
|
||||
parameters:
|
||||
- name: changeset
|
||||
in: query
|
||||
description: Changeset
|
||||
required: false
|
||||
type: string
|
||||
- name: path
|
||||
in: query
|
||||
description: File
|
||||
required: false
|
||||
type: string
|
||||
- name: repository
|
||||
in: query
|
||||
description: Mozilla repository for this changeset (default to mozilla-central)
|
||||
required: false
|
||||
type: string
|
||||
- name: suite
|
||||
in: query
|
||||
description: Filter the coverage using this test suite
|
||||
required: false
|
||||
type: string
|
||||
- name: platform
|
||||
in: query
|
||||
description: Filter the coverage using this platform
|
||||
required: false
|
||||
type: string
|
||||
- name: changeset
|
||||
in: query
|
||||
description: Changeset
|
||||
required: false
|
||||
type: string
|
||||
- name: path
|
||||
in: query
|
||||
description: File
|
||||
required: false
|
||||
type: string
|
||||
- name: repository
|
||||
in: query
|
||||
description: Mozilla repository for this changeset (default to mozilla-central)
|
||||
required: false
|
||||
type: string
|
||||
- name: suite
|
||||
in: query
|
||||
description: Filter the coverage using this test suite
|
||||
required: false
|
||||
type: string
|
||||
- name: platform
|
||||
in: query
|
||||
description: Filter the coverage using this platform
|
||||
required: false
|
||||
type: string
|
||||
responses:
|
||||
200:
|
||||
description: Code coverage information for a given file or directory at a given changeset
|
||||
|
@ -62,36 +62,36 @@ paths:
|
|||
get:
|
||||
operationId: "code_coverage_backend.api.coverage_history"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: query
|
||||
description: Mozilla repository for these reports (default to mozilla-central)
|
||||
required: false
|
||||
type: string
|
||||
- name: start
|
||||
in: query
|
||||
description: Start timestamp for the history date range (default to a year before end)
|
||||
required: false
|
||||
type: string
|
||||
- name: end
|
||||
in: query
|
||||
description: End timestamp for the history date range (default to current timestamp)
|
||||
required: false
|
||||
type: string
|
||||
- name: path
|
||||
in: query
|
||||
description: Path of the repository folder to get coverage info on.
|
||||
required: false
|
||||
type: string
|
||||
- name: suite
|
||||
in: query
|
||||
description: Filter the coverage using this test suite
|
||||
required: false
|
||||
type: string
|
||||
- name: platform
|
||||
in: query
|
||||
description: Filter the coverage using this platform
|
||||
required: false
|
||||
type: string
|
||||
- name: repository
|
||||
in: query
|
||||
description: Mozilla repository for these reports (default to mozilla-central)
|
||||
required: false
|
||||
type: string
|
||||
- name: start
|
||||
in: query
|
||||
description: Start timestamp for the history date range (default to a year before end)
|
||||
required: false
|
||||
type: string
|
||||
- name: end
|
||||
in: query
|
||||
description: End timestamp for the history date range (default to current timestamp)
|
||||
required: false
|
||||
type: string
|
||||
- name: path
|
||||
in: query
|
||||
description: Path of the repository folder to get coverage info on.
|
||||
required: false
|
||||
type: string
|
||||
- name: suite
|
||||
in: query
|
||||
description: Filter the coverage using this test suite
|
||||
required: false
|
||||
type: string
|
||||
- name: platform
|
||||
in: query
|
||||
description: Filter the coverage using this platform
|
||||
required: false
|
||||
type: string
|
||||
responses:
|
||||
200:
|
||||
description: Overall coverage of specified path over a period of time
|
||||
|
@ -111,11 +111,11 @@ paths:
|
|||
get:
|
||||
operationId: "code_coverage_backend.api.coverage_filters"
|
||||
parameters:
|
||||
- name: repository
|
||||
in: query
|
||||
description: Mozilla repository for these reports (default to mozilla-central)
|
||||
required: false
|
||||
type: string
|
||||
- name: repository
|
||||
in: query
|
||||
description: Mozilla repository for these reports (default to mozilla-central)
|
||||
required: false
|
||||
type: string
|
||||
responses:
|
||||
200:
|
||||
description: Available filters on the endpoints
|
||||
|
|
|
@ -44,11 +44,11 @@ Write your local configuration as YAML:
|
|||
common:
|
||||
APP_CHANNEL: dev
|
||||
bot:
|
||||
BACKEND_HOST: 'http://localhost:8000'
|
||||
BACKEND_HOST: "http://localhost:8000"
|
||||
EMAIL_ADDRESSES: []
|
||||
PHABRICATOR_TOKEN: api-xxx
|
||||
PHABRICATOR_ENABLED: false
|
||||
PHABRICATOR_URL: 'https://phabricator-dev.allizom.org/api/'
|
||||
PHABRICATOR_URL: "https://phabricator-dev.allizom.org/api/"
|
||||
GOOGLE_CLOUD_STORAGE: null
|
||||
```
|
||||
|
||||
|
|
|
@ -1,85 +1,83 @@
|
|||
{
|
||||
"bindings": [],
|
||||
"bindings": [],
|
||||
"metadata": {
|
||||
"description": "Automatically build code coverage reports",
|
||||
"emailOnError": true,
|
||||
"name": "Code coverage hook (CHANNEL)",
|
||||
"owner": "mcastelluccio@mozilla.com"
|
||||
},
|
||||
"schedule": ["0 0 0 * * *"],
|
||||
"task": {
|
||||
"created": {
|
||||
"$fromNow": "0 seconds"
|
||||
},
|
||||
"deadline": {
|
||||
"$fromNow": "4 hours"
|
||||
},
|
||||
"expires": {
|
||||
"$fromNow": "1 month"
|
||||
},
|
||||
"extra": {},
|
||||
"metadata": {
|
||||
"description": "Automatically build code coverage reports",
|
||||
"emailOnError": true,
|
||||
"name": "Code coverage hook (CHANNEL)",
|
||||
"owner": "mcastelluccio@mozilla.com"
|
||||
"description": "",
|
||||
"name": "Code Coverage aggregation task - cron (CHANNEL)",
|
||||
"owner": "mcastelluccio@mozilla.com",
|
||||
"source": "https://github.com/mozilla/code-coverage"
|
||||
},
|
||||
"schedule": [
|
||||
"0 0 0 * * *"
|
||||
"payload": {
|
||||
"artifacts": {
|
||||
"public/chunk_mapping.tar.xz": {
|
||||
"path": "/chunk_mapping.tar.xz",
|
||||
"type": "file"
|
||||
},
|
||||
"public/per_chunk_mapping.tar.xz": {
|
||||
"path": "/per_chunk_mapping.tar.xz",
|
||||
"type": "file"
|
||||
},
|
||||
"public/zero_coverage_report.json": {
|
||||
"path": "/zero_coverage_report.json",
|
||||
"type": "file"
|
||||
},
|
||||
"public/commit_coverage.json.zst": {
|
||||
"path": "/commit_coverage.json.zst",
|
||||
"type": "file"
|
||||
}
|
||||
},
|
||||
"cache": {
|
||||
"code-coverage-bot-CHANNEL": "/cache"
|
||||
},
|
||||
"capabilities": {},
|
||||
"command": [
|
||||
"code-coverage-cron",
|
||||
"--taskcluster-secret",
|
||||
"project/relman/code-coverage/runtime-CHANNEL",
|
||||
"--cache-root",
|
||||
"/cache",
|
||||
"--working-dir",
|
||||
"/build"
|
||||
],
|
||||
"env": {},
|
||||
"features": {
|
||||
"taskclusterProxy": true
|
||||
},
|
||||
"image": "mozilla/code-coverage:bot-REVISION",
|
||||
"maxRunTime": 14400
|
||||
},
|
||||
"priority": "normal",
|
||||
"provisionerId": "aws-provisioner-v1",
|
||||
"retries": 5,
|
||||
"routes": [],
|
||||
"schedulerId": "-",
|
||||
"scopes": [
|
||||
"secrets:get:project/relman/code-coverage/runtime-CHANNEL",
|
||||
"docker-worker:cache:code-coverage-bot-CHANNEL",
|
||||
"index:insert-task:project.relman.code-coverage.CHANNEL.cron.*"
|
||||
],
|
||||
"task": {
|
||||
"created": {
|
||||
"$fromNow": "0 seconds"
|
||||
},
|
||||
"deadline": {
|
||||
"$fromNow": "4 hours"
|
||||
},
|
||||
"expires": {
|
||||
"$fromNow": "1 month"
|
||||
},
|
||||
"extra": {},
|
||||
"metadata": {
|
||||
"description": "",
|
||||
"name": "Code Coverage aggregation task - cron (CHANNEL)",
|
||||
"owner": "mcastelluccio@mozilla.com",
|
||||
"source": "https://github.com/mozilla/code-coverage"
|
||||
},
|
||||
"payload": {
|
||||
"artifacts": {
|
||||
"public/chunk_mapping.tar.xz": {
|
||||
"path": "/chunk_mapping.tar.xz",
|
||||
"type": "file"
|
||||
},
|
||||
"public/per_chunk_mapping.tar.xz": {
|
||||
"path": "/per_chunk_mapping.tar.xz",
|
||||
"type": "file"
|
||||
},
|
||||
"public/zero_coverage_report.json": {
|
||||
"path": "/zero_coverage_report.json",
|
||||
"type": "file"
|
||||
},
|
||||
"public/commit_coverage.json.zst": {
|
||||
"path": "/commit_coverage.json.zst",
|
||||
"type": "file"
|
||||
}
|
||||
},
|
||||
"cache": {
|
||||
"code-coverage-bot-CHANNEL": "/cache"
|
||||
},
|
||||
"capabilities": {},
|
||||
"command": [
|
||||
"code-coverage-cron",
|
||||
"--taskcluster-secret",
|
||||
"project/relman/code-coverage/runtime-CHANNEL",
|
||||
"--cache-root",
|
||||
"/cache",
|
||||
"--working-dir",
|
||||
"/build"
|
||||
],
|
||||
"env": {},
|
||||
"features": {
|
||||
"taskclusterProxy": true
|
||||
},
|
||||
"image": "mozilla/code-coverage:bot-REVISION",
|
||||
"maxRunTime": 14400
|
||||
},
|
||||
"priority": "normal",
|
||||
"provisionerId": "aws-provisioner-v1",
|
||||
"retries": 5,
|
||||
"routes": [],
|
||||
"schedulerId": "-",
|
||||
"scopes": [
|
||||
"secrets:get:project/relman/code-coverage/runtime-CHANNEL",
|
||||
"docker-worker:cache:code-coverage-bot-CHANNEL",
|
||||
"index:insert-task:project.relman.code-coverage.CHANNEL.cron.*"
|
||||
],
|
||||
"tags": {},
|
||||
"workerType": "relman-svc-memory"
|
||||
},
|
||||
"triggerSchema": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
}
|
||||
"tags": {},
|
||||
"workerType": "relman-svc-memory"
|
||||
},
|
||||
"triggerSchema": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,94 +1,93 @@
|
|||
{
|
||||
"bindings": [],
|
||||
"metadata": {
|
||||
"description": "Automatically build code coverage reports",
|
||||
"emailOnError": true,
|
||||
"name": "Code coverage hook (CHANNEL)",
|
||||
"owner": "mcastelluccio@mozilla.com"
|
||||
},
|
||||
"task": {
|
||||
"$merge": [
|
||||
{
|
||||
"$if": "'taskGroupId' in payload",
|
||||
"else": {},
|
||||
"then": {
|
||||
"taskGroupId": {
|
||||
"$eval": "payload.taskGroupId"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"created": {
|
||||
"$fromNow": "0 seconds"
|
||||
},
|
||||
"deadline": {
|
||||
"$fromNow": "4 hours"
|
||||
},
|
||||
"expires": {
|
||||
"$fromNow": "1 month"
|
||||
},
|
||||
"extra": {},
|
||||
"metadata": {
|
||||
"description": "",
|
||||
"name": {
|
||||
"$if": "'taskName' in payload",
|
||||
"else": "Code Coverage aggregation task - repo (CHANNEL)",
|
||||
"then": {
|
||||
"$eval": "payload.taskName"
|
||||
}
|
||||
},
|
||||
"owner": "mcastelluccio@mozilla.com",
|
||||
"source": "https://github.com/mozilla/code-coverage"
|
||||
},
|
||||
"payload": {
|
||||
|
||||
"artifacts": {
|
||||
"public/code-coverage-report.json": {
|
||||
"expires": {"$fromNow": "2 weeks"},
|
||||
"path": "/build/ccov-reports/all.all.json",
|
||||
"type": "file"
|
||||
}
|
||||
},
|
||||
"cache": {
|
||||
"code-coverage-bot-CHANNEL": "/cache"
|
||||
},
|
||||
"capabilities": {},
|
||||
"command": [
|
||||
"code-coverage-repo",
|
||||
"--taskcluster-secret",
|
||||
"project/relman/code-coverage/runtime-CHANNEL",
|
||||
"--cache-root",
|
||||
"/cache",
|
||||
"--working-dir",
|
||||
"/build"
|
||||
],
|
||||
"env": {
|
||||
"$eval": "payload"
|
||||
},
|
||||
"features": {
|
||||
"taskclusterProxy": true
|
||||
},
|
||||
"image": "mozilla/code-coverage:bot-REVISION",
|
||||
"maxRunTime": 14400
|
||||
},
|
||||
"priority": "normal",
|
||||
"provisionerId": "aws-provisioner-v1",
|
||||
"retries": 5,
|
||||
"routes": [],
|
||||
"schedulerId": "-",
|
||||
"scopes": [
|
||||
"secrets:get:project/relman/code-coverage/runtime-CHANNEL",
|
||||
"notify:email:*",
|
||||
"docker-worker:cache:code-coverage-bot-CHANNEL",
|
||||
"index:insert-task:project.relman.code-coverage.CHANNEL.repo.*"
|
||||
],
|
||||
"tags": {},
|
||||
"workerType": "relman-svc-memory"
|
||||
"bindings": [],
|
||||
"metadata": {
|
||||
"description": "Automatically build code coverage reports",
|
||||
"emailOnError": true,
|
||||
"name": "Code coverage hook (CHANNEL)",
|
||||
"owner": "mcastelluccio@mozilla.com"
|
||||
},
|
||||
"task": {
|
||||
"$merge": [
|
||||
{
|
||||
"$if": "'taskGroupId' in payload",
|
||||
"else": {},
|
||||
"then": {
|
||||
"taskGroupId": {
|
||||
"$eval": "payload.taskGroupId"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"created": {
|
||||
"$fromNow": "0 seconds"
|
||||
},
|
||||
"deadline": {
|
||||
"$fromNow": "4 hours"
|
||||
},
|
||||
"expires": {
|
||||
"$fromNow": "1 month"
|
||||
},
|
||||
"extra": {},
|
||||
"metadata": {
|
||||
"description": "",
|
||||
"name": {
|
||||
"$if": "'taskName' in payload",
|
||||
"else": "Code Coverage aggregation task - repo (CHANNEL)",
|
||||
"then": {
|
||||
"$eval": "payload.taskName"
|
||||
}
|
||||
]
|
||||
},
|
||||
"triggerSchema": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"owner": "mcastelluccio@mozilla.com",
|
||||
"source": "https://github.com/mozilla/code-coverage"
|
||||
},
|
||||
"payload": {
|
||||
"artifacts": {
|
||||
"public/code-coverage-report.json": {
|
||||
"expires": { "$fromNow": "2 weeks" },
|
||||
"path": "/build/ccov-reports/all.all.json",
|
||||
"type": "file"
|
||||
}
|
||||
},
|
||||
"cache": {
|
||||
"code-coverage-bot-CHANNEL": "/cache"
|
||||
},
|
||||
"capabilities": {},
|
||||
"command": [
|
||||
"code-coverage-repo",
|
||||
"--taskcluster-secret",
|
||||
"project/relman/code-coverage/runtime-CHANNEL",
|
||||
"--cache-root",
|
||||
"/cache",
|
||||
"--working-dir",
|
||||
"/build"
|
||||
],
|
||||
"env": {
|
||||
"$eval": "payload"
|
||||
},
|
||||
"features": {
|
||||
"taskclusterProxy": true
|
||||
},
|
||||
"image": "mozilla/code-coverage:bot-REVISION",
|
||||
"maxRunTime": 14400
|
||||
},
|
||||
"priority": "normal",
|
||||
"provisionerId": "aws-provisioner-v1",
|
||||
"retries": 5,
|
||||
"routes": [],
|
||||
"schedulerId": "-",
|
||||
"scopes": [
|
||||
"secrets:get:project/relman/code-coverage/runtime-CHANNEL",
|
||||
"notify:email:*",
|
||||
"docker-worker:cache:code-coverage-bot-CHANNEL",
|
||||
"index:insert-task:project.relman.code-coverage.CHANNEL.repo.*"
|
||||
],
|
||||
"tags": {},
|
||||
"workerType": "relman-svc-memory"
|
||||
}
|
||||
]
|
||||
},
|
||||
"triggerSchema": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
{
|
||||
"plugins": [
|
||||
["prismjs", {
|
||||
"languages": ["javascript", "clike", "python", "cpp", "c", "css", "java"],
|
||||
[
|
||||
"prismjs",
|
||||
{
|
||||
"languages": [
|
||||
"javascript",
|
||||
"clike",
|
||||
"python",
|
||||
"cpp",
|
||||
"c",
|
||||
"css",
|
||||
"java"
|
||||
],
|
||||
"plugins": ["line-numbers"],
|
||||
"theme": "solarizedlight",
|
||||
"css": true
|
||||
}]
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# Mozilla Code Coverage frontend
|
||||
|
||||
This is a simple JavaScript application displaying information from the Mozilla code coverage backend (hosted as https://coverage.moz.tools)
|
||||
|
||||
You can use it right now from [coverage.moz.tools](https://coverage.moz.tools/)
|
||||
You can use it right now from [coverage.moz.tools](https://coverage.moz.tools/)
|
||||
|
||||
## File viewer
|
||||
|
||||
|
|
|
@ -1,181 +1,196 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>mozilla-central coverage</title>
|
||||
<link rel="icon" href="<%=require('../assets/moz-fav-bw-rgb.png').default%>" type="image/png" />
|
||||
</head>
|
||||
<body>
|
||||
<script id="zerocoverage" type="x-tmpl-mustache">
|
||||
<div id="browser">
|
||||
<h2>
|
||||
<nav>
|
||||
{{#navbar}}
|
||||
<a href="{{ route }}">{{ name }}</a>
|
||||
{{/navbar}}
|
||||
</nav>
|
||||
<span> : {{ total }} files</span>
|
||||
</h2>
|
||||
|
||||
<div class="table">
|
||||
<div class="header">
|
||||
<span class="filename">File name</span>
|
||||
<span>Children</span>
|
||||
<span>Functions</span>
|
||||
<span>First push</span>
|
||||
<span>Last push</span>
|
||||
<span>Size</span>
|
||||
<span>Commits</span>
|
||||
</div>
|
||||
|
||||
{{#entries}}
|
||||
<div class="row">
|
||||
<span class="filename"><a href="{{ entry_url }}">{{ dir }}</a></span>
|
||||
<span>{{ stats.children }}</span>
|
||||
<span>{{ stats.funcs }}</span>
|
||||
<span>{{ stats.first_push_date }}</span>
|
||||
<span>{{ stats.last_push_date }}</span>
|
||||
<span>{{ stats.size }}</span>
|
||||
<span>{{ stats.commits }}</span>
|
||||
</div>
|
||||
{{/entries}}
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script id="file_coverage" type="x-tmpl-mustache">
|
||||
<div id="file">
|
||||
<h2>
|
||||
<nav>
|
||||
{{#navbar}}
|
||||
<a href="{{ route }}">{{ name }}</a>
|
||||
{{/navbar}}
|
||||
</nav>
|
||||
</h2>
|
||||
|
||||
<div class="help">
|
||||
<p class="no_data"><samp> </samp><span>Non-instrumented</span></p>
|
||||
<p class="uncovered"><samp> </samp><span>Uncovered</span></p>
|
||||
<p class="covered"><samp> </samp><span>Covered</span></p>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
{{#lines}}
|
||||
<tr class="{{ css_class }}" id="l{{ nb }}">
|
||||
<td><a class="scroll" href="{{ route }}">{{ nb }}</a></td>
|
||||
<td>
|
||||
<pre class="language-{{ language }}"><code>{{ line }}</code></pre>
|
||||
</td>
|
||||
<td>
|
||||
{{#hits}}
|
||||
<span class="{{ hits.unit }}" title="This line has been hit {{ coverage }} times.">{{ hits.nb }} {{ hits.unit }}</span>
|
||||
{{/hits}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/lines}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script id="file_browser" type="x-tmpl-mustache">
|
||||
<div id="browser">
|
||||
<h2>
|
||||
<nav>
|
||||
{{#navbar}}
|
||||
<a href="{{ route }}">{{ name }}</a>
|
||||
{{/navbar}}
|
||||
</nav>
|
||||
<span> : {{ files.length }} files</span>
|
||||
</h2>
|
||||
|
||||
<div class="table">
|
||||
<div class="header">
|
||||
<span class="filename">File name</span>
|
||||
<span>Children</span>
|
||||
<span>Coverage</span>
|
||||
</div>
|
||||
|
||||
{{#files}}
|
||||
<div class="row">
|
||||
<span class="filename"><a href="{{ route }}">{{ file_name }}</a></span>
|
||||
<span>{{ children }}</span>
|
||||
<span class="coverage_{{ range }}">{{ coveragePercent }} %</span>
|
||||
</div>
|
||||
{{/files}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script id="history_point" type="x-tmpl-mustache">
|
||||
<span>Revision <samp>{{ revision }}</samp> from {{ date }}</span>
|
||||
</script>
|
||||
|
||||
<script id="menu_browser" type="x-tmpl-mustache">
|
||||
<a class="item" href="#view=zero">View the zero coverage report</a>
|
||||
<input class="revision" type="text" name="revision" placeholder="Mercurial revision" value="{{revision}}"></input>
|
||||
<select name="platform">
|
||||
<option value="all">All platforms</option>
|
||||
{{#platforms}}
|
||||
<option {{#selected}}selected="selected"{{/selected}} value="{{name}}">{{name}}</option>
|
||||
{{/platforms}}
|
||||
</select>
|
||||
<select name="suite">
|
||||
<option value="all">All test suites</option>
|
||||
{{#suites}}
|
||||
<option {{#selected}}selected="selected"{{/selected}} value="{{name}}">{{name}}</option>
|
||||
{{/suites}}
|
||||
</select>
|
||||
</script>
|
||||
|
||||
<script id="menu_zero" type="x-tmpl-mustache">
|
||||
{{#filters}}
|
||||
<input type="checkbox" name="{{ key }}" id="{{ key }}" {{#checked}}checked="checked"{{/checked}}>
|
||||
<label for="{{ key }}">{{ message }}</label>
|
||||
{{#needs_explanation}}
|
||||
<div class="tooltip">
|
||||
<span class="questionbox">?</span>
|
||||
<span class="tooltiptext">For <strong>JavaScript</strong>, files with at least one function where all functions are uncovered.
|
||||
<br />For <strong>C/C++/other languages</strong>, files which have no covered lines.</span>
|
||||
</div>
|
||||
{{/needs_explanation}}
|
||||
{{/filters}}
|
||||
|
||||
<select name="last_push" id="last_push">
|
||||
{{#last_pushes}}
|
||||
<option {{#selected}}selected="selected"{{/selected}} value="{{value}}">{{message}}</option>
|
||||
{{/last_pushes}}
|
||||
</select>
|
||||
</script>
|
||||
|
||||
<header>
|
||||
<div class="logo">
|
||||
<img src="<%=require('../assets/moz-logo-black.png').default%>" alt="Moz://a"/>
|
||||
<a href="#view=directory">Code Coverage</a>
|
||||
</div>
|
||||
<div id="menu"></div>
|
||||
</header>
|
||||
|
||||
<main id="main">
|
||||
<div id="message" class="message loading">Loading...</div>
|
||||
<div id="history">
|
||||
<div class="ct-chart"></div>
|
||||
<div id="history_details">Hover a point to see its details</div>
|
||||
</div>
|
||||
<div id="output"></div>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<a target="_blank" href="https://github.com/mozilla/code-coverage">
|
||||
<img src="<%=require('../assets/github.png').default%>" alt="GitHub" />
|
||||
</a>
|
||||
<a target="_blank" href="https://github.com/mozilla/code-coverage/issues/new?labels=frontend,bug&title=Issue+with+the+frontend">Report an issue</a>
|
||||
•
|
||||
<a target="_blank" href="https://github.com/mozilla/code-coverage/fork" aria-label="Fork mozilla/code-coverage on GitHub">Fork mozilla/code-coverage</a>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>mozilla-central coverage</title>
|
||||
<link
|
||||
rel="icon"
|
||||
href="<%=require('../assets/moz-fav-bw-rgb.png').default%>"
|
||||
type="image/png"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<script id="zerocoverage" type="x-tmpl-mustache">
|
||||
<div id="browser">
|
||||
<h2>
|
||||
<nav>
|
||||
{{#navbar}}
|
||||
<a href="{{ route }}">{{ name }}</a>
|
||||
{{/navbar}}
|
||||
</nav>
|
||||
<span> : {{ total }} files</span>
|
||||
</h2>
|
||||
|
||||
<div class="table">
|
||||
<div class="header">
|
||||
<span class="filename">File name</span>
|
||||
<span>Children</span>
|
||||
<span>Functions</span>
|
||||
<span>First push</span>
|
||||
<span>Last push</span>
|
||||
<span>Size</span>
|
||||
<span>Commits</span>
|
||||
</div>
|
||||
|
||||
{{#entries}}
|
||||
<div class="row">
|
||||
<span class="filename"><a href="{{ entry_url }}">{{ dir }}</a></span>
|
||||
<span>{{ stats.children }}</span>
|
||||
<span>{{ stats.funcs }}</span>
|
||||
<span>{{ stats.first_push_date }}</span>
|
||||
<span>{{ stats.last_push_date }}</span>
|
||||
<span>{{ stats.size }}</span>
|
||||
<span>{{ stats.commits }}</span>
|
||||
</div>
|
||||
{{/entries}}
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script id="file_coverage" type="x-tmpl-mustache">
|
||||
<div id="file">
|
||||
<h2>
|
||||
<nav>
|
||||
{{#navbar}}
|
||||
<a href="{{ route }}">{{ name }}</a>
|
||||
{{/navbar}}
|
||||
</nav>
|
||||
</h2>
|
||||
|
||||
<div class="help">
|
||||
<p class="no_data"><samp> </samp><span>Non-instrumented</span></p>
|
||||
<p class="uncovered"><samp> </samp><span>Uncovered</span></p>
|
||||
<p class="covered"><samp> </samp><span>Covered</span></p>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<tbody>
|
||||
{{#lines}}
|
||||
<tr class="{{ css_class }}" id="l{{ nb }}">
|
||||
<td><a class="scroll" href="{{ route }}">{{ nb }}</a></td>
|
||||
<td>
|
||||
<pre class="language-{{ language }}"><code>{{ line }}</code></pre>
|
||||
</td>
|
||||
<td>
|
||||
{{#hits}}
|
||||
<span class="{{ hits.unit }}" title="This line has been hit {{ coverage }} times.">{{ hits.nb }} {{ hits.unit }}</span>
|
||||
{{/hits}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/lines}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script id="file_browser" type="x-tmpl-mustache">
|
||||
<div id="browser">
|
||||
<h2>
|
||||
<nav>
|
||||
{{#navbar}}
|
||||
<a href="{{ route }}">{{ name }}</a>
|
||||
{{/navbar}}
|
||||
</nav>
|
||||
<span> : {{ files.length }} files</span>
|
||||
</h2>
|
||||
|
||||
<div class="table">
|
||||
<div class="header">
|
||||
<span class="filename">File name</span>
|
||||
<span>Children</span>
|
||||
<span>Coverage</span>
|
||||
</div>
|
||||
|
||||
{{#files}}
|
||||
<div class="row">
|
||||
<span class="filename"><a href="{{ route }}">{{ file_name }}</a></span>
|
||||
<span>{{ children }}</span>
|
||||
<span class="coverage_{{ range }}">{{ coveragePercent }} %</span>
|
||||
</div>
|
||||
{{/files}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script id="history_point" type="x-tmpl-mustache">
|
||||
<span>Revision <samp>{{ revision }}</samp> from {{ date }}</span>
|
||||
</script>
|
||||
|
||||
<script id="menu_browser" type="x-tmpl-mustache">
|
||||
<a class="item" href="#view=zero">View the zero coverage report</a>
|
||||
<input class="revision" type="text" name="revision" placeholder="Mercurial revision" value="{{revision}}"></input>
|
||||
<select name="platform">
|
||||
<option value="all">All platforms</option>
|
||||
{{#platforms}}
|
||||
<option {{#selected}}selected="selected"{{/selected}} value="{{name}}">{{name}}</option>
|
||||
{{/platforms}}
|
||||
</select>
|
||||
<select name="suite">
|
||||
<option value="all">All test suites</option>
|
||||
{{#suites}}
|
||||
<option {{#selected}}selected="selected"{{/selected}} value="{{name}}">{{name}}</option>
|
||||
{{/suites}}
|
||||
</select>
|
||||
</script>
|
||||
|
||||
<script id="menu_zero" type="x-tmpl-mustache">
|
||||
{{#filters}}
|
||||
<input type="checkbox" name="{{ key }}" id="{{ key }}" {{#checked}}checked="checked"{{/checked}}>
|
||||
<label for="{{ key }}">{{ message }}</label>
|
||||
{{#needs_explanation}}
|
||||
<div class="tooltip">
|
||||
<span class="questionbox">?</span>
|
||||
<span class="tooltiptext">For <strong>JavaScript</strong>, files with at least one function where all functions are uncovered.
|
||||
<br />For <strong>C/C++/other languages</strong>, files which have no covered lines.</span>
|
||||
</div>
|
||||
{{/needs_explanation}}
|
||||
{{/filters}}
|
||||
|
||||
<select name="last_push" id="last_push">
|
||||
{{#last_pushes}}
|
||||
<option {{#selected}}selected="selected"{{/selected}} value="{{value}}">{{message}}</option>
|
||||
{{/last_pushes}}
|
||||
</select>
|
||||
</script>
|
||||
|
||||
<header>
|
||||
<div class="logo">
|
||||
<img
|
||||
src="<%=require('../assets/moz-logo-black.png').default%>"
|
||||
alt="Moz://a"
|
||||
/>
|
||||
<a href="#view=directory">Code Coverage</a>
|
||||
</div>
|
||||
<div id="menu"></div>
|
||||
</header>
|
||||
|
||||
<main id="main">
|
||||
<div id="message" class="message loading">Loading...</div>
|
||||
<div id="history">
|
||||
<div class="ct-chart"></div>
|
||||
<div id="history_details">Hover a point to see its details</div>
|
||||
</div>
|
||||
<div id="output"></div>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<a target="_blank" href="https://github.com/mozilla/code-coverage">
|
||||
<img src="<%=require('../assets/github.png').default%>" alt="GitHub" />
|
||||
</a>
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://github.com/mozilla/code-coverage/issues/new?labels=frontend,bug&title=Issue+with+the+frontend"
|
||||
>Report an issue</a
|
||||
>
|
||||
•
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://github.com/mozilla/code-coverage/fork"
|
||||
aria-label="Fork mozilla/code-coverage on GitHub"
|
||||
>Fork mozilla/code-coverage</a
|
||||
>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -5,8 +5,8 @@ import { ZERO_COVERAGE_FILTERS } from "./zero_coverage_report.js";
|
|||
export const REV_LATEST = "latest";
|
||||
|
||||
function domContentLoaded() {
|
||||
return new Promise(resolve =>
|
||||
document.addEventListener("DOMContentLoaded", resolve)
|
||||
return new Promise((resolve) =>
|
||||
document.addEventListener("DOMContentLoaded", resolve),
|
||||
);
|
||||
}
|
||||
export const DOM_READY = domContentLoaded();
|
||||
|
@ -21,7 +21,7 @@ export async function main(load, display) {
|
|||
|
||||
// Full workflow, loading then displaying data
|
||||
// used for following updates
|
||||
const full = async function() {
|
||||
const full = async function () {
|
||||
const data = await load();
|
||||
await display(data);
|
||||
};
|
||||
|
@ -56,7 +56,7 @@ function cacheSet(cache, key, value) {
|
|||
|
||||
cache[key] = {
|
||||
val: value,
|
||||
time: now
|
||||
time: now,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ export async function getPathCoverage(path, changeset, platform, suite) {
|
|||
params += `&suite=${suite}`;
|
||||
}
|
||||
const response = await fetch(
|
||||
`${COVERAGE_BACKEND_HOST}/v2/path?${params}`
|
||||
`${COVERAGE_BACKEND_HOST}/v2/path?${params}`,
|
||||
).catch(alert);
|
||||
if (response.status !== 200) {
|
||||
throw new Error(response.status + " - " + response.statusText);
|
||||
|
@ -118,7 +118,7 @@ export async function getHistory(path, platform, suite) {
|
|||
|
||||
// Check data has coverage values
|
||||
// These values are missing when going above 2 levels right now
|
||||
const coverage = data.filter(point => {
|
||||
const coverage = data.filter((point) => {
|
||||
return point.coverage !== null;
|
||||
});
|
||||
if (coverage.length === 0) {
|
||||
|
@ -137,7 +137,7 @@ export async function getZeroCoverageData() {
|
|||
}
|
||||
|
||||
const response = await fetch(
|
||||
"https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/project.relman.code-coverage.production.cron.latest/artifacts/public/zero_coverage_report.json"
|
||||
"https://firefox-ci-tc.services.mozilla.com/api/index/v1/task/project.relman.code-coverage.production.cron.latest/artifacts/public/zero_coverage_report.json",
|
||||
);
|
||||
data = await response.json();
|
||||
|
||||
|
@ -198,12 +198,12 @@ export async function getSource(file, revision) {
|
|||
|
||||
// Filtering.
|
||||
|
||||
const getThirdPartyPaths = (function() {
|
||||
const getThirdPartyPaths = (function () {
|
||||
let paths = null;
|
||||
return async function() {
|
||||
return async function () {
|
||||
if (!paths) {
|
||||
const response = await getSource("tools/rewriting/ThirdPartyPaths.txt");
|
||||
paths = response.split("\n").filter(path => path !== "");
|
||||
paths = response.split("\n").filter((path) => path !== "");
|
||||
}
|
||||
|
||||
return paths;
|
||||
|
@ -217,7 +217,7 @@ export async function filterThirdParty(files) {
|
|||
|
||||
const paths = await getThirdPartyPaths();
|
||||
|
||||
return files.filter(file => {
|
||||
return files.filter((file) => {
|
||||
for (const path of paths) {
|
||||
if (file.path.startsWith(path)) {
|
||||
return false;
|
||||
|
@ -240,7 +240,7 @@ export function filterLanguages(files) {
|
|||
"hxx",
|
||||
"hpp",
|
||||
"inl",
|
||||
"inc"
|
||||
"inc",
|
||||
];
|
||||
const js = isEnabled("js");
|
||||
const jsExtensions = [
|
||||
|
@ -251,23 +251,23 @@ export function filterLanguages(files) {
|
|||
"xml",
|
||||
"xul",
|
||||
"xhtml",
|
||||
"html"
|
||||
"html",
|
||||
];
|
||||
const java = isEnabled("java");
|
||||
const javaExtensions = ["java"];
|
||||
const rust = isEnabled("rust");
|
||||
const rustExtensions = ["rs"];
|
||||
|
||||
return files.filter(file => {
|
||||
return files.filter((file) => {
|
||||
if (file.type === "directory") {
|
||||
return true;
|
||||
} else if (cppExtensions.find(ext => file.path.endsWith("." + ext))) {
|
||||
} else if (cppExtensions.find((ext) => file.path.endsWith("." + ext))) {
|
||||
return cpp;
|
||||
} else if (jsExtensions.find(ext => file.path.endsWith("." + ext))) {
|
||||
} else if (jsExtensions.find((ext) => file.path.endsWith("." + ext))) {
|
||||
return js;
|
||||
} else if (rustExtensions.find(ext => file.path.endsWith("." + ext))) {
|
||||
} else if (rustExtensions.find((ext) => file.path.endsWith("." + ext))) {
|
||||
return rust;
|
||||
} else if (javaExtensions.find(ext => file.path.endsWith("." + ext))) {
|
||||
} else if (javaExtensions.find((ext) => file.path.endsWith("." + ext))) {
|
||||
return java;
|
||||
}
|
||||
console.warn("Unknown language for " + file.path);
|
||||
|
@ -280,7 +280,7 @@ export function filterHeaders(files) {
|
|||
return files;
|
||||
}
|
||||
|
||||
return files.filter(file => !file.path.endsWith(".h"));
|
||||
return files.filter((file) => !file.path.endsWith(".h"));
|
||||
}
|
||||
|
||||
export function filterCompletelyUncovered(files) {
|
||||
|
@ -288,7 +288,7 @@ export function filterCompletelyUncovered(files) {
|
|||
return files;
|
||||
}
|
||||
|
||||
return files.filter(file => file.uncovered);
|
||||
return files.filter((file) => file.uncovered);
|
||||
}
|
||||
|
||||
export function filterLastPushDate(files) {
|
||||
|
@ -308,7 +308,7 @@ export function filterLastPushDate(files) {
|
|||
return files;
|
||||
}
|
||||
|
||||
return files.filter(file => {
|
||||
return files.filter((file) => {
|
||||
const lastPushDate = new Date(file.lastPushDate);
|
||||
if (
|
||||
lastPushDate.getTime() <= upperLimit.getTime() &&
|
||||
|
@ -329,17 +329,17 @@ export function buildNavbar(path, revision) {
|
|||
const links = [
|
||||
{
|
||||
name: "mozilla-central",
|
||||
route: buildRoute({ path: "", revision })
|
||||
}
|
||||
route: buildRoute({ path: "", revision }),
|
||||
},
|
||||
];
|
||||
return links.concat(
|
||||
path.split("/").map(file => {
|
||||
path.split("/").map((file) => {
|
||||
base += (base ? "/" : "") + file;
|
||||
return {
|
||||
name: file,
|
||||
route: buildRoute({ path: base, view: "directory", revision })
|
||||
route: buildRoute({ path: base, view: "directory", revision }),
|
||||
};
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,7 @@ export function show(id, node) {
|
|||
export function render(template, data, target) {
|
||||
const output = Mustache.render(
|
||||
document.getElementById(template).innerHTML,
|
||||
data
|
||||
data,
|
||||
);
|
||||
const box = document.getElementById(target);
|
||||
|
||||
|
|
|
@ -11,12 +11,12 @@ import {
|
|||
buildNavbar,
|
||||
render,
|
||||
getSource,
|
||||
getFilters
|
||||
getFilters,
|
||||
} from "./common.js";
|
||||
import { buildRoute, monitorOptions, readRoute, updateRoute } from "./route.js";
|
||||
import {
|
||||
zeroCoverageDisplay,
|
||||
zeroCoverageMenu
|
||||
zeroCoverageMenu,
|
||||
} from "./zero_coverage_report.js";
|
||||
import "normalize.css/normalize.css";
|
||||
import "./style.scss";
|
||||
|
@ -31,18 +31,18 @@ const VIEW_FILE = "file";
|
|||
function browserMenu(revision, filters, route) {
|
||||
const context = {
|
||||
revision,
|
||||
platforms: filters.platforms.map(p => {
|
||||
platforms: filters.platforms.map((p) => {
|
||||
return {
|
||||
name: p,
|
||||
selected: p === route.platform
|
||||
selected: p === route.platform,
|
||||
};
|
||||
}),
|
||||
suites: filters.suites.map(s => {
|
||||
suites: filters.suites.map((s) => {
|
||||
return {
|
||||
name: s,
|
||||
selected: s === route.suite
|
||||
selected: s === route.suite,
|
||||
};
|
||||
})
|
||||
}),
|
||||
};
|
||||
render("menu_browser", context, "menu");
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ async function graphHistory(history, path) {
|
|||
return;
|
||||
}
|
||||
|
||||
const dateStr = function(timestamp) {
|
||||
const dateStr = function (timestamp) {
|
||||
const date = new Date(timestamp);
|
||||
return `${date.getDate()}/${date.getMonth() + 1}/${date.getFullYear()}`;
|
||||
};
|
||||
|
@ -62,44 +62,44 @@ async function graphHistory(history, path) {
|
|||
series: [
|
||||
{
|
||||
name: "History",
|
||||
data: history.map(push => {
|
||||
data: history.map((push) => {
|
||||
return {
|
||||
x: push.date * 1000,
|
||||
y: push.coverage
|
||||
y: push.coverage,
|
||||
};
|
||||
})
|
||||
}
|
||||
]
|
||||
}),
|
||||
},
|
||||
],
|
||||
};
|
||||
const config = {
|
||||
// Display dates on a linear scale
|
||||
axisX: {
|
||||
type: Chartist.FixedScaleAxis,
|
||||
divisor: 20,
|
||||
labelInterpolationFnc: dateStr
|
||||
labelInterpolationFnc: dateStr,
|
||||
},
|
||||
|
||||
// Fix display bug when points are too close
|
||||
lineSmooth: Chartist.Interpolation.cardinal({
|
||||
tension: 1
|
||||
})
|
||||
tension: 1,
|
||||
}),
|
||||
};
|
||||
const elt = show("history").querySelector(".ct-chart");
|
||||
const chart = new Chartist.Line(elt, data, config);
|
||||
|
||||
chart.on("draw", function(evt) {
|
||||
chart.on("draw", function (evt) {
|
||||
if (evt.type === "point") {
|
||||
// Load revision from graph when a point is clicked
|
||||
const revision = history[evt.index].changeset;
|
||||
evt.element._node.onclick = function() {
|
||||
evt.element._node.onclick = function () {
|
||||
updateRoute({ revision });
|
||||
};
|
||||
|
||||
// Display revision from graph when a point is overed
|
||||
evt.element._node.onmouseover = function() {
|
||||
evt.element._node.onmouseover = function () {
|
||||
const ctx = {
|
||||
revision: revision.substring(0, 12),
|
||||
date: dateStr(evt.value.x)
|
||||
date: dateStr(evt.value.x),
|
||||
};
|
||||
render("history_point", ctx, "history_details");
|
||||
};
|
||||
|
@ -110,10 +110,10 @@ async function graphHistory(history, path) {
|
|||
async function showDirectory(dir, revision, files) {
|
||||
const context = {
|
||||
navbar: buildNavbar(dir, revision),
|
||||
files: files.map(file => {
|
||||
files: files.map((file) => {
|
||||
file.route = buildRoute({
|
||||
path: file.path,
|
||||
view: file.type
|
||||
view: file.type,
|
||||
});
|
||||
|
||||
// Calc decimal range to make a nice coloration
|
||||
|
@ -131,7 +131,7 @@ async function showDirectory(dir, revision, files) {
|
|||
}
|
||||
|
||||
return this.path;
|
||||
}
|
||||
},
|
||||
};
|
||||
render("file_browser", context, "output");
|
||||
}
|
||||
|
@ -173,17 +173,17 @@ async function showFile(source, file, revision, selectedLine) {
|
|||
if (coverage >= 1000000) {
|
||||
hits = {
|
||||
nb: parseInt(coverage / 1000000),
|
||||
unit: "M"
|
||||
unit: "M",
|
||||
};
|
||||
} else if (coverage >= 1000) {
|
||||
hits = {
|
||||
nb: parseInt(coverage / 1000),
|
||||
unit: "k"
|
||||
unit: "k",
|
||||
};
|
||||
} else if (coverage > 0) {
|
||||
hits = {
|
||||
nb: coverage,
|
||||
unit: ""
|
||||
unit: "",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -201,9 +201,9 @@ async function showFile(source, file, revision, selectedLine) {
|
|||
coverage,
|
||||
line: line || " ",
|
||||
css_class: cssClass,
|
||||
route: buildRoute({ line: nb })
|
||||
route: buildRoute({ line: nb }),
|
||||
};
|
||||
})
|
||||
}),
|
||||
};
|
||||
|
||||
hide("message");
|
||||
|
@ -215,7 +215,7 @@ async function showFile(source, file, revision, selectedLine) {
|
|||
const line = output.querySelector("#l" + selectedLine);
|
||||
line.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "center"
|
||||
block: "center",
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ async function load() {
|
|||
"Loading coverage data for " +
|
||||
(route.path || "mozilla-central") +
|
||||
" @ " +
|
||||
(route.revision || REV_LATEST)
|
||||
(route.revision || REV_LATEST),
|
||||
);
|
||||
|
||||
// Load only zero coverage for that specific view
|
||||
|
@ -244,7 +244,7 @@ async function load() {
|
|||
view: VIEW_ZERO_COVERAGE,
|
||||
path: route.path,
|
||||
zeroCoverage,
|
||||
route
|
||||
route,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ async function load() {
|
|||
const [coverage, filters, viewData] = await Promise.all([
|
||||
getPathCoverage(route.path, route.revision, route.platform, route.suite),
|
||||
getFilters(),
|
||||
viewContent
|
||||
viewContent,
|
||||
]);
|
||||
|
||||
return {
|
||||
|
@ -271,7 +271,7 @@ async function load() {
|
|||
route,
|
||||
coverage,
|
||||
filters,
|
||||
viewData
|
||||
viewData,
|
||||
};
|
||||
} catch (err) {
|
||||
console.warn("Failed to load coverage", err);
|
||||
|
@ -296,7 +296,7 @@ export async function display(data) {
|
|||
data.viewData,
|
||||
data.coverage,
|
||||
data.revision,
|
||||
data.route.line
|
||||
data.route.line,
|
||||
);
|
||||
} else {
|
||||
message("error", "Invalid view : " + data.view);
|
||||
|
|
|
@ -6,7 +6,7 @@ export function readRoute() {
|
|||
const hash = window.location.hash.substring(1);
|
||||
const pairs = hash.split("&");
|
||||
const out = {};
|
||||
pairs.forEach(pair => {
|
||||
pairs.forEach((pair) => {
|
||||
const [key, value] = pair.split("=");
|
||||
if (!key) {
|
||||
return;
|
||||
|
@ -36,7 +36,7 @@ export function buildRoute(params) {
|
|||
return (
|
||||
"#" +
|
||||
Object.keys(route)
|
||||
.map(k => encodeURIComponent(k) + "=" + encodeURIComponent(route[k]))
|
||||
.map((k) => encodeURIComponent(k) + "=" + encodeURIComponent(route[k]))
|
||||
.join("&")
|
||||
);
|
||||
}
|
||||
|
@ -64,13 +64,13 @@ export function monitorOptions(currentData) {
|
|||
for (const field of fields) {
|
||||
if (field.classList.contains("scroll")) {
|
||||
// On a scroll event, update display without any data loading
|
||||
field.onclick = async evt => {
|
||||
field.onclick = async (evt) => {
|
||||
evt.preventDefault();
|
||||
updateRouteImmediate(evt.target.hash, currentData);
|
||||
};
|
||||
} else if (field.type === "text") {
|
||||
// React on enter
|
||||
field.onkeydown = async evt => {
|
||||
field.onkeydown = async (evt) => {
|
||||
if (evt.keyCode === 13) {
|
||||
const params = {};
|
||||
params[evt.target.name] = evt.target.value;
|
||||
|
@ -79,7 +79,7 @@ export function monitorOptions(currentData) {
|
|||
};
|
||||
} else {
|
||||
// React on change
|
||||
field.onchange = async evt => {
|
||||
field.onchange = async (evt) => {
|
||||
let value = evt.target.value;
|
||||
if (evt.target.type === "checkbox") {
|
||||
value = evt.target.checked ? "on" : "off";
|
||||
|
|
|
@ -18,7 +18,20 @@ body {
|
|||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
font-family:
|
||||
BlinkMacSystemFont,
|
||||
-apple-system,
|
||||
"Segoe UI",
|
||||
Roboto,
|
||||
Oxygen,
|
||||
Ubuntu,
|
||||
Cantarell,
|
||||
"Fira Sans",
|
||||
"Droid Sans",
|
||||
"Helvetica Neue",
|
||||
Helvetica,
|
||||
Arial,
|
||||
sans-serif;
|
||||
|
||||
background-color: white;
|
||||
|
||||
|
@ -135,7 +148,7 @@ nav {
|
|||
|
||||
a:not(:last-child)::after {
|
||||
content: "/";
|
||||
color: #CCC;
|
||||
color: #ccc;
|
||||
margin: 0 2px;
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +157,7 @@ nav {
|
|||
#browser {
|
||||
max-width: $small_screen;
|
||||
margin: 0 auto;
|
||||
padding: .5em;
|
||||
padding: 0.5em;
|
||||
|
||||
.table {
|
||||
display: table;
|
||||
|
@ -214,7 +227,7 @@ nav {
|
|||
}
|
||||
|
||||
&.row {
|
||||
&:nth-child(2n+3) {
|
||||
&:nth-child(2n + 3) {
|
||||
background: hsl(0, 0%, 98%);
|
||||
}
|
||||
|
||||
|
@ -229,7 +242,8 @@ nav {
|
|||
h2 {
|
||||
width: 100%;
|
||||
|
||||
nav, span {
|
||||
nav,
|
||||
span {
|
||||
display: inline-block;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
@ -310,7 +324,7 @@ $samp_size: 20px;
|
|||
color: grey;
|
||||
font-size: 1em;
|
||||
vertical-align: middle;
|
||||
border-right: 1px solid #CCC;
|
||||
border-right: 1px solid #ccc;
|
||||
font-family: monospace;
|
||||
background: #f5f2f0;
|
||||
padding: 0 2px;
|
||||
|
@ -438,7 +452,7 @@ $samp_size: 20px;
|
|||
&::after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
bottom: 100%; /* At the top of the tooltip */
|
||||
bottom: 100%; /* At the top of the tooltip */
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
|
|
|
@ -8,45 +8,45 @@ import {
|
|||
filterLanguages,
|
||||
filterHeaders,
|
||||
filterCompletelyUncovered,
|
||||
filterLastPushDate
|
||||
filterLastPushDate,
|
||||
} from "./common.js";
|
||||
import { buildRoute } from "./route.js";
|
||||
|
||||
export const ZERO_COVERAGE_FILTERS = {
|
||||
third_party: {
|
||||
name: "Show third-party files",
|
||||
default_value: "on"
|
||||
default_value: "on",
|
||||
},
|
||||
headers: {
|
||||
name: "Show headers",
|
||||
default_value: "off"
|
||||
default_value: "off",
|
||||
},
|
||||
completely_uncovered: {
|
||||
name: "Show completely uncovered files only",
|
||||
default_value: "off"
|
||||
default_value: "off",
|
||||
},
|
||||
cpp: {
|
||||
name: "C/C++",
|
||||
default_value: "on"
|
||||
default_value: "on",
|
||||
},
|
||||
js: {
|
||||
name: "JavaScript",
|
||||
default_value: "on"
|
||||
default_value: "on",
|
||||
},
|
||||
java: {
|
||||
name: "Java",
|
||||
default_value: "on"
|
||||
default_value: "on",
|
||||
},
|
||||
rust: {
|
||||
name: "Rust",
|
||||
default_value: "on"
|
||||
}
|
||||
default_value: "on",
|
||||
},
|
||||
};
|
||||
const ZERO_COVERAGE_PUSHES = {
|
||||
all: "All",
|
||||
one_year: "0 < 1 year",
|
||||
two_years: "1 < 2 years",
|
||||
older_than_two_years: "Older than 2 years"
|
||||
older_than_two_years: "Older than 2 years",
|
||||
};
|
||||
|
||||
export function zeroCoverageMenu(route) {
|
||||
|
@ -56,7 +56,7 @@ export function zeroCoverageMenu(route) {
|
|||
key,
|
||||
message: filter.name,
|
||||
checked: isEnabled(key),
|
||||
needs_explanation: key === "completely_uncovered"
|
||||
needs_explanation: key === "completely_uncovered",
|
||||
};
|
||||
}),
|
||||
last_pushes: Object.entries(ZERO_COVERAGE_PUSHES).map(
|
||||
|
@ -64,10 +64,10 @@ export function zeroCoverageMenu(route) {
|
|||
return {
|
||||
value,
|
||||
message,
|
||||
selected: route.last_push === value
|
||||
selected: route.last_push === value,
|
||||
};
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
};
|
||||
render("menu_zero", context, "menu");
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ function getBaseStats(file, children) {
|
|||
first_push_date: file.first_push_date,
|
||||
last_push_date: file.last_push_date,
|
||||
size: file.size,
|
||||
commits: file.commits
|
||||
commits: file.commits,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -119,11 +119,11 @@ function cumStats(prevStats, newStats) {
|
|||
prevStats.commits += newStats.commits;
|
||||
prevStats.first_push_date = getMinDate(
|
||||
prevStats.first_push_date,
|
||||
newStats.first_push_date
|
||||
newStats.first_push_date,
|
||||
);
|
||||
prevStats.last_push_date = getMinDate(
|
||||
prevStats.last_push_date,
|
||||
newStats.last_push_date
|
||||
newStats.last_push_date,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ export async function zeroCoverageDisplay(data, dir) {
|
|||
hide("history");
|
||||
message(
|
||||
"loading",
|
||||
"Loading zero coverage report for " + (dir || "mozilla-central")
|
||||
"Loading zero coverage report for " + (dir || "mozilla-central"),
|
||||
);
|
||||
|
||||
while (dir.endsWith("/")) {
|
||||
|
@ -143,9 +143,9 @@ export async function zeroCoverageDisplay(data, dir) {
|
|||
dir = "";
|
||||
}
|
||||
|
||||
let files = data.files.filter(file => file.name.startsWith(dir));
|
||||
let files = data.files.filter((file) => file.name.startsWith(dir));
|
||||
// TODO: Do this in the backend directly!
|
||||
files.forEach(file => {
|
||||
files.forEach((file) => {
|
||||
file.path = file.name;
|
||||
});
|
||||
files = await filterThirdParty(files);
|
||||
|
@ -183,14 +183,14 @@ export async function zeroCoverageDisplay(data, dir) {
|
|||
if (this.stats.children !== 0) {
|
||||
return buildRoute({
|
||||
view: "zero",
|
||||
path
|
||||
path,
|
||||
});
|
||||
}
|
||||
// Fully reset the url when moving back to file view
|
||||
return `#view=file&revision=${revision}&path=${path}`;
|
||||
},
|
||||
navbar: buildNavbar(dir),
|
||||
total: files.length
|
||||
total: files.length,
|
||||
};
|
||||
|
||||
hide("message");
|
||||
|
|
|
@ -1,29 +1,28 @@
|
|||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const ESLintPlugin = require('eslint-webpack-plugin');
|
||||
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const ESLintPlugin = require("eslint-webpack-plugin");
|
||||
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
|
||||
module.exports = {
|
||||
entry: ['babel-polyfill', 'index.js'],
|
||||
entry: ["babel-polyfill", "index.js"],
|
||||
output: {
|
||||
path: __dirname + '/dist',
|
||||
publicPath: '',
|
||||
filename: 'coverage-[hash].js'
|
||||
path: __dirname + "/dist",
|
||||
publicPath: "",
|
||||
filename: "coverage-[hash].js",
|
||||
},
|
||||
plugins: [
|
||||
new ESLintPlugin(),
|
||||
new CleanWebpackPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'src/base.html',
|
||||
template: "src/base.html",
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: 'coverage-[hash].css',
|
||||
filename: "coverage-[hash].css",
|
||||
}),
|
||||
new webpack.EnvironmentPlugin({
|
||||
BACKEND_URL: 'http://localhost:8000',
|
||||
BACKEND_URL: "http://localhost:8000",
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
|
@ -32,42 +31,36 @@ module.exports = {
|
|||
test: /\.js$/,
|
||||
exclude: /(node_modules)/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: ['@babel/preset-env']
|
||||
}
|
||||
}
|
||||
presets: ["@babel/preset-env"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.s[ac]ss$/i,
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
'css-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: [MiniCssExtractPlugin.loader, 'css-loader'],
|
||||
use: [MiniCssExtractPlugin.loader, "css-loader"],
|
||||
},
|
||||
{
|
||||
test: /\.(png|svg|jpg|gif)$/,
|
||||
use: [
|
||||
'file-loader'
|
||||
]
|
||||
use: ["file-loader"],
|
||||
},
|
||||
],
|
||||
},
|
||||
devServer: {
|
||||
contentBase: path.join(__dirname, 'dist'),
|
||||
devServer: {
|
||||
contentBase: path.join(__dirname, "dist"),
|
||||
compress: true,
|
||||
port: 9000
|
||||
port: 9000,
|
||||
},
|
||||
resolve: {
|
||||
modules: [
|
||||
path.join(__dirname, 'node_modules'),
|
||||
path.join(__dirname, 'assets'),
|
||||
path.join(__dirname, 'src'),
|
||||
path.join(__dirname, "node_modules"),
|
||||
path.join(__dirname, "assets"),
|
||||
path.join(__dirname, "src"),
|
||||
],
|
||||
},
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const { merge } = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
const { merge } = require("webpack-merge");
|
||||
const common = require("./webpack.common.js");
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'development',
|
||||
devtool: 'inline-source-map',
|
||||
mode: "development",
|
||||
devtool: "inline-source-map",
|
||||
devServer: {
|
||||
contentBase: './dist'
|
||||
}
|
||||
contentBase: "./dist",
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
const { merge } = require('webpack-merge');
|
||||
const common = require('./webpack.common.js');
|
||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
||||
const TerserJSPlugin = require('terser-webpack-plugin');
|
||||
const { merge } = require("webpack-merge");
|
||||
const common = require("./webpack.common.js");
|
||||
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
|
||||
const TerserJSPlugin = require("terser-webpack-plugin");
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
mode: "production",
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserJSPlugin({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<!doctype html>
|
||||
<meta charset="utf-8" />
|
||||
<title>Redirecting to zero coverage report</title>
|
||||
<meta http-equiv="refresh" content="0; URL=index.html#zero:">
|
||||
<link rel="canonical" href="index.html#zero:">
|
||||
<meta http-equiv="refresh" content="0; URL=index.html#zero:" />
|
||||
<link rel="canonical" href="index.html#zero:" />
|
||||
|
|
Загрузка…
Ссылка в новой задаче