I did this as a warm-up to using [React hooks](https://reactjs.org/docs/hooks-intro.html), which provide a better way to accomplish stateful things and side effects using functional components. This allows all components to be written in the same style, improves testability, facilitates code reuse, etc.
There's [a intro here](https://reactjs.org/docs/hooks-intro.html) which links to [Dan's talk at React Conf](https://www.youtube.com/watch?time_continue=3599&v=dpw9EHDh2bM) which does a really good job of explaining why hooks are a good way to write components. He describes hooks as being the electrons and neutrons to components which are atoms. Low-level functionality which was always there in React, though not as accessibly or visibly.
This adds a lint rule that enforces "the rule of hooks" which says they have to be declared at the top level in the functional component.
I don't think this changeset does a fabulous job of showing off the improvements hooks allows, though I think it is still a good direction for this code.
* Label all deprecated services as such
This will change
service_requests_total{category="other",family="cocoapods",service="cocoapods_apps"} 76
to
service_requests_total{category="other",family="cocoapods",service="deprecated_cocoapods_apps"} 76
* Fix tests
This moves a few helpers from `lib/` to `services/`:
build-status.js
build-status.spec.js
color-formatters.js
color-formatters.spec.js
contributor-count.js
licenses.js
licenses.spec.js
php-version.js
php-version.spec.js
text-formatters.js
text-formatters.spec.js
version.js
version.spec.js
And one from `lib/` to `core/`:
unhandled-rejection.spec.js
The diff is long, but the changes are straightforward.
Ref #2832
The buildpack config doesn't seem to be needed. This would affect review apps, staging, and self-hosting.
Also, devDependencies are installed by default during the build: https://devcenter.heroku.com/changelog-items/1376
By removing `NPM_CONFIG_PRODUCTION=false` we allow these to be pruned so they're kept out of the slug. This also has the advantage of creating a test environment in PRs where missing production dependencies will cause things to break. That'd be a good thing!
This picks up #2068 by adding per-badge stats as discussed in #966.
It ensures every service has a unique `name` property. By default this comes from the class name, and is overridden in all the various places where the class names are duplicated. (Some of those don't seem that useful, like the various download interval services, though those need to be refactored down into a single service anyway.) Tests enforce the names are unique. These are the names used by the service-test runner, so it's a good idea to make them unique anyway. (It was sort of strange before that you had to specify `nuget` instead of e.g. `resharper`.)
I've added validation to `deprecatedService` and `redirector`, and required that every `route` has a `base`, even if it's an empty string.
The name is used to generate unique metric labels, generating metrics like these:
```
service_requests_total{category="activity",family="eclipse-marketplace",service="eclipse_marketplace_update"} 2
service_requests_total{category="activity",family="npm",service="npm_collaborators"} 3
service_requests_total{category="activity",family="steam",service="steam_file_release_date"} 2
service_requests_total{category="analysis",family="ansible",service="ansible_galaxy_content_quality_score"} 2
service_requests_total{category="analysis",family="cii-best-practices",service="cii_best_practices_service"} 4
service_requests_total{category="analysis",family="cocoapods",service="cocoapods_docs"} 2
service_requests_total{category="analysis",family="codacy",service="codacy_grade"} 3
service_requests_total{category="analysis",family="coverity",service="coverity_scan"} 2
service_requests_total{category="analysis",family="coverity",service="deprecated_coverity_ondemand"} 2
service_requests_total{category="analysis",family="dependabot",service="dependabot_semver_compatibility"} 3
service_requests_total{category="analysis",family="lgtm",service="lgtm_alerts"} 2
service_requests_total{category="analysis",family="lgtm",service="lgtm_grade"} 3
service_requests_total{category="analysis",family="snyk",service="snyk_vulnerability_git_hub"} 4
service_requests_total{category="analysis",family="snyk",service="snyk_vulnerability_npm"} 5
service_requests_total{category="analysis",family="symfony",service="sensiolabs_i_redirector"} 1
service_requests_total{category="analysis",family="symfony",service="symfony_insight_grade"} 1
service_requests_total{category="build",family="appveyor",service="app_veyor_ci"} 3
service_requests_total{category="build",family="appveyor",service="app_veyor_tests"} 6
service_requests_total{category="build",family="azure-devops",service="azure_dev_ops_build"} 6
service_requests_total{category="build",family="azure-devops",service="azure_dev_ops_release"} 5
service_requests_total{category="build",family="azure-devops",service="azure_dev_ops_tests"} 6
service_requests_total{category="build",family="azure-devops",service="vso_build_redirector"} 2
service_requests_total{category="build",family="azure-devops",service="vso_release_redirector"} 1
service_requests_total{category="build",family="bitbucket",service="bitbucket_pipelines"} 5
service_requests_total{category="build",family="circleci",service="circle_ci"} 5
```
This is predicated on being able to use Prometheus's [`rate()`](https://prometheus.io/docs/prometheus/latest/querying/functions/#rate) function to visualize a counter's rate of change, as mentioned at https://github.com/badges/shields/issues/2068#issuecomment-466696561. Otherwise the stats will be disrupted every time a server restarts.
The metrics only appear on new-style services.
This switches to the new mozilla add-ons API.
It's not a completely like-for-like replacement. I was able to replicate the version, users and rating badges but we no longer have total download stats. We've got weekly downloads instead, so I've redirected `/d` to the new `/dw`
closes#3079
While I was doing #3090 I realized the work in #3012 did not handle legacy services.
I tested this manually with `/librariesio/release/hex/phoenix.svg?color=blue` and it works.