Commit Graph

939 Commits

Author SHA1 Message Date
Paul Melnikow
18b98a30e3 Reorganize server and service test runner (#2781)
Ref #2698
2019-01-16 16:30:18 -05:00
Paul Melnikow
79af2840f3 Fix overriding bind address on CLI (#2773)
This fixes e.g. `node server 8080 0.0.0.0`.

Ref #2772.
2019-01-15 14:38:55 -05:00
Paul Melnikow
fa5309400d PaaS, CI, and production-friendly config (#2626)
This implements the configuration mechanism I described in #2621. The heavy lifting is delegated to [node-config](https://github.com/lorenwest/node-config) with a minor assist from [dotenv](https://github.com/motdotla/dotenv).

`private/secret.json` has been replaced with environment variables and/or `config/local.yml`. See `doc/server-secrets.md`.
2019-01-06 10:42:09 -05:00
Paul Melnikow
7150b37831 Add test of the server entrypoint (#2613)
The server's entrypoint is an important bit of code which is not covered by our tests. This adds a test which should cover it.
2019-01-01 22:58:54 -05:00
Paul Melnikow
5c665a70da Overhaul initialization pattern for server + server tests (#2519)
Because `server.js` was long a monolith, there are a bunch of shims in place to facilitate unit testing. A few of the test suites share port 1111 which means if one of them fails to set up, the port won't be freed and other unrelated tests will fail. Some of the tests which trigger server setup include timeouts which were added to give setup code time to run. In one the test suites, we actually modify `process.argv`, which seems completely gross.

This implements a few changes which improve this:

1. Separate the server from the server startup script, splitting out `lib/server.js`.
2. Inject config into the server and validate the config schema.
3. Inject config into the service test runner.
4. Use `portfinder`, a popular utility for grabbing open ports during testing.
5. Switch more of the setup code from callbacks to async-await.

Overall it leaves everything acting more reliably and looking rather cleaner, if in a few places more verbose.

It also fixes the root cause of #1455, a `setTimeout` in `rate-limit`. Off and on during development of this changeset, Mocha would decide not to exit, and that turned out to be the culprit.

Fix #1455
2018-12-23 11:24:22 -05:00
Paul Melnikow
b8461aa921 Rewrite [DynamicXml] and [DynamicYaml] badges (#2487)
- A little related cleanup in `server.js`: remove a couple import renames.
2018-12-12 16:52:47 -05:00
Paul Melnikow
6a737b7b38 Rewrite the DynamicJson badge (#2399)
This starts the rewrite of the dynamic badges. I've pulled into BaseService an initial version of the query param validation from #2325.

I've extended from BaseJsonService to avoid duplicating the deserialization logic, though it means there is a bit of duplicated code among the three dynamic services. The way to unravel this would be to move the logic from `_requestJson` and friends from the base classes into functions so DynamicJson can inherit from BaseDynamic. Would that be worth it?

This introduces a regression of #1446 for this badge.

Close #2345
2018-12-06 16:45:40 -05:00
Paul Melnikow
54a36e9474 Refactor cache-header handling and config, create NonMemoryCachingBaseService, rewrite [flip] (#2360)
There's a lot going on in this PR, though it's all interdependent, so the only way I can see to break it up into smaller pieces would be serially.

1. I completely refactored the functions for managing cache headers. These have been added to `services/cache-headers.js`, and in some ways set the stage for the rest of this PR.

    - There are ample higher-level test of the functionality via `request-handler`. Refactoring these tests was deferred. Cache headers were previously dealt with in three places:
        - `request-handler.js`, for the dynamic badges. This function now calls `setCacheHeaders`.
        - `base-static.js`, for the static badges. This method now calls the wordy `serverHasBeenUpSinceResourceCached` and `setCacheHeadersForStaticResource`.
        - The bitFlip badge in `server.js`. 👈 This is what set all this in motion. This badge has been refactored to a new-style service based on a new `NoncachingBaseService` which does not use the Shields in-memory cache that the dynamic badges user.
    - I'm open to clearer names for `NoncachingBaseService`, which is kind of terrible. Absent alternatives, I wrote a short essay of clarification in the docstring. 😝 

2. In the process of writing `NoncachingBaseService`, I discovered it takes several lines of code to instantiate and invoke a service. These would be duplicated in three or four places in production code, and in lots and lots of tests. I kept the line that goes from regex to namedParams (for reasons) and moved the rest into a static method called `invoke()`, which instantiates and invokes the service. This _replaced_ the instance method `invokeHandler`.
    - I gently reworked the unit tests to use `invoke` instead of `invokeHandler`– generally for the better.
    - I made a small change to `BaseStatic`. Now it invokes `handle()` async as the dynamic badges do. This way it could use `BaseService.invoke()`.

3. There was logic in `request-handler` for processing environment variables, validating them, and setting defaults. This could have been lifted whole-hog to `services/cache-headers.js`, though I didn't do that. Instead I moved it to `server-config.js`. Ideally `server-config` is the only module that should access `process.env`. This puts the defaults and config validation in one place, decouples the config schema from the entire rest of the application, and significantly simplifies our ability to test different configs, particularly on small units of code. (We were doing this well enough before in `request-handler.spec`, though it required mutating the environment, which was kludgy.) Some of the `request-handler` tests could be rewritten at a higher level, with lower-level data-driven tests directly against `cache-headers`.
2018-12-01 13:57:34 -05:00
Paul Melnikow
73fcc1ccac Deprecate old [StaticBadge] using a redirect (#2333)
Now that the static badge has been moved in #2284, next in line for cleaning out `server.js` is this “static badge, old format.” I imagine this route is _very, very old_. (I wouldn’t be surprised if it’s not used at all. I’d be curious to see some stats on that endpoint. If it's not regularly getting requests I could see dropping it.)

In the case of URLs which have permanently changed, an approach I’d like to try is issuing a 301 Redirect.

The benefit is that if a user pastes the URL into the address bar while they are previewing or editing it, the browser will replace the address with the corrected URL when it loads. I figure this will cause some people to update their URLs with no effort, simply because they previewed the badge in their browser, and others to change over, if they notice it.

We incur a slight cost, which is a second request. However many browsers cache the 301’s indefinitely, and we can set an effectively infinite cache duration so the CDN and most other downstream caches will keep them a long time. And handling the redirect is extremely cheap.

This is a nice way to preserve backward compatibility of old routes without having to complicate the new route, such as in the case of vso -> azure-devops. For maintenance purposes, the route that redirects can effectively be treated separately.

It’s also a nice, gentle, and confidence-inspiring way to signal that users should update their URLs.

We could generalize this code, though I think this is a good place to start. This route is tricky because it needs to be loaded last, complicating a reusable solution.
2018-11-17 15:22:03 -05:00
Paul Melnikow
065dd570ad Move [StaticBadge] to own service & add test; also affects [gitter] (#2284)
This picks up @RedSparr0w's work in #1802.

1. The handler for the static badge is moved into its own service with a synchronous handler. Avoiding an async call may make the static badges slightly faster, though it may be worth profiling this if it turns out we want asynchronous static badges in the future. If it doesn't make a performance difference we could make this handler `async` like the others.
2. Most of the custom static-badge logic is in a BaseStaticBadge base class.
3. Rewrite the static Gitter badge to use BaseStaticBadge.
4. A bit of minor cleanup in related functions.
2018-11-16 19:21:48 -05:00
Paul Melnikow
51897b3c7e Precompute text width using a lookup table (#2311)
This simplifies and further optimizes text-width computation by computing the entire width table in advance, and serializing it in the style of QuickTextMeasurer (#1390). This entirely removes the need for PDFKit at runtime. This has the advantage of fixing #1305 – more generally: producing the same result everywhere – without having to deploy a copy of Verdana.

The lifting is delegated to these three libraries, which are housed in a monorepo: https://github.com/metabolize/anafanafo

I'd be happy to move it into the badges org if folks want to collaborate on maintaining them.

QuickTextMeasurer took kerning pairs into account, whereas this implementation does not. I was thinking kerning would be a necessary refinement, though this seems to work well enough.

I dropped in a binary-search package to traverse the data structure, in part to conserve space. This causes a moderate performance regression, though there is ample room for improving on that: https://github.com/badges/shields/pull/2311#issuecomment-439182704
2018-11-15 17:27:21 -05:00
chris48s
b68ac16092 Move NPM package files out of /lib ; affects [resharper nuget myget dub chocolatey github] (#2300)
* move gh-badges files out of /lib

As far as possible, this is just moving files
around and updating paths however there are 2
functional changes in this commit:
- remove use of lib/register-chai-plugins.spec
  in badge-cli.spec.js
- remove use of starRating()
  in text-measurer.spec.js

* update service tests that use colorscheme.json

* split package.json in two

* clean up import

* don't hard-code path

* start a changelog

* put a license file in the package dir

* re-organise documentation 📚

* don't pack test files

* remove favicon from Makefile

* give package its own test command

* link the docs better in README
2018-11-15 18:48:01 +00:00
Marcin Mielnicki
bc4bd79e90 Metrics with Prometheus (#2069)
* Basic process metrics

* Enable Prometheus by an environment variable

* Code formatting

* Documentation for Prometheus metrics

* Link from README to documentation of Prometheus

* Link from README to documentation of Prometheus

* Link from README to documentation of Prometheus

* Separate module for metrics + tests

* Metrics limited by IP

* Metrics are forbidded for all requets by default

* Code refactoring

* allowedIps passed as a string to PrometheusMetrics

* Handle missing config

* METRICS_PROMETHEUS_ALLOWED_IPS added to documentation

* Log info about enabled metrics

* Unused code removed

* package-lock.json updated

* prom-client updated to 11.1.2

* Code refactoring

* Do not read IP address from X-Forwarder-For header
2018-11-04 18:54:43 +01:00
Paul Melnikow
83ac6ff1b3 Enforce use of template literals (#2242)
This is consistent with what we're pretty much already doing, and saves us from making the request during code review.

These were all autofixed and most of them seem easier to read. Some in the legacy services should be rewritten in more legible forms during refactor (ie using intermediate variables, or using request’s qs option). There are some in helper functions and elsewhere that should get rewritten separately. I don't want to change them in this PR because the changes will get lost in this diff, though we could identify them here and fix them before or just after.
2018-11-02 17:11:44 -04:00
chris48s
819202bcf3 treat label as override in static badge (#2116)
closes #2112
2018-10-06 15:09:59 +01:00
Paul Melnikow
1b307864b4 Prettify the files in the project root (#2041)
Follow on to #2009
2018-09-02 12:10:23 -07:00
Paul Melnikow
102141123b Unify lint rules and clean lint (#2009)
Now that server.js is emptied out, it makes sense to eliminate the differences between the top-level .js files and everything else.
2018-09-01 11:08:17 -07:00
chris48s
e294dc4edc refactor [circleci] integration (#1927)
* refactor [circleci] integration
2018-08-28 15:49:43 +01:00
Paul Melnikow
bedba47d77 Move legacy services from server.js into services/ (#1958)
This builds on the work of #1931 by moving the legacy services into `services/`.
2018-08-27 13:29:54 -04:00
Paul Melnikow
302c8606ff Rewrite [pypi]; affects [npm] (#1922) 2018-08-27 07:46:06 -04:00
Paul Melnikow
942466aa92 Allow migrating legacy services to services/ (#1931) 2018-08-21 23:38:12 -04:00
Pyves
82bc90cec1 Deprecated VersionEye (#1953) 2018-08-20 20:04:11 +01:00
Paul Melnikow
656326d693 Rewrite [appveyor] tests badge (#1940) 2018-08-20 14:49:59 -04:00
Pyves
886cde72d5 Rewrite [Wercker] service (#1920) 2018-08-16 22:03:15 +01:00
Pyves
b0070ff861 [GitHub] Error message customisation for all status codes (#1888) 2018-08-14 18:57:24 +01:00
Paul Melnikow
0c703c11b5 Rewrite [uptimerobot] (#1891) 2018-08-12 21:47:30 -07:00
Danial
b2af8f7a04 [GitHub] support issue tags with "/" character (#1902)
* support tags with "/" character
2018-08-12 15:20:30 +12:00
Paul Melnikow
9007658fd0 Refactor and test [github] token persistence (#1863)
Ref #1848 #1205
2018-08-11 20:13:40 -04:00
Paul Melnikow
8af48c0a21 Minor tweaks in [github] auth code (#1862)
* Move / rework is-valid-token

* TokenPool: Add allValidTokenIds method

* Minor cleanup in server.js
2018-08-09 07:22:54 -04:00
Paul Melnikow
c11d97a192 Refactor [github] initialization (#1861)
This creates a new convenience class which consolidates all the Github initialization. It supports dependency injection and facilitates refactoring the persistence along the lines of #1205.

Also ref #1848
2018-08-09 07:20:57 -04:00
Paul Melnikow
e3b100504d Add Joi-based request validation to BaseJsonService and rewrite [NPM] and [node] badges (#1743)
When JSON responses come back, they are sometimes not in the format expected by the API. As a result we have a lot of defensive coding (expressions like `(data || {}).someProperty`) to avoid exceptions being thrown in badge processing. Often we rely on the `try` blocks that wrap so much of the badge-processing code, which catch all JavaScript exceptions and return some error result, usually **invalid**. The problem with this is that these `try` blocks catch all sorts of programmer errors too, so when we see **invalid** we don't know whether the API returned something unexpected, or we've made a mistake. We also spend a lot of time writing defensive tests around malformed responses, and creating and maintaining the defensive coding.

A better solution is to validate the API responses using declarative contracts. Here the programmer says exactly what they expect from the API. That way, if the response isn't what we expect we can just say it's an **invalid json response**. And if our code then throws an exception, well that's our mistake; when we catch that we can call it a **shields internal error**. It's also less code and less error-prone. Over time we may be confident enough in the contracts that we won't need so many tests of malformed responses. The contract doesn't need to describe the entire response, only the part that's needed. Unknown keys can simply be dropped, preventing unvalidated parts of the response from creeping into the code. Checking what's in our response before calling values on it also makes our code more secure.

I used Joi here, since we're already using it for testing. There may be another contracts library that's a better fit, though I think we could look at that later.

Those changes are in base.js.

The rest is a rewrite of the remaining NPM badges, including the extraction of an NpmBase class. Inspired by @chris48s's work in #1740, this class splits the service concerns into fetching, validation, transformation, and rendering. This is treated as a design pattern. See the PR discussion for more. There are two URL patterns, one which allows specifying a tag (used by e.g. the version badge `https://img.shields.io/npm/v/npm/next.svg`), and the other which does not accept a tag (e.g. the license badge `https://img.shields.io/npm/l/express.svg`). Subclasses like NpmLicense and NpmTypeDefinitions can specify the URL fragment, examples, the validation schema for the chunk of the package data they use, and a render function. The NpmVersion subclass uses a different endpoint, so it overrides the `handle` implementation from NpmBase.

The remaining services using BaseJsonService are shimmed, so they will keep working after the changes.
2018-08-08 17:08:16 -04:00
Pyves
e1affea266 [GitHub] Fix undefined badges (#1816) 2018-08-08 20:57:57 +01:00
Paul Melnikow
56fcb2e5ba GithubApiProvider: injectible interface for code that calls github (#1812) 2018-08-07 16:46:12 -04:00
Paul Melnikow
2ff71dab6a Start cleaning up github auth routes (#1813)
- Move github token debug route to separate module
- Use crypto.timingSafeEqual
- Rename getTokenDebugInfo -> serializeDebugInfo
2018-08-01 21:58:11 -04:00
Pyves
9335f607aa [conda] Fixed wrong variable name (#1817) 2018-07-31 22:27:06 +01:00
Danial
3a54b5dc84 eslint enable comma-dangle always-multiline (#1818)
https://eslint.org/docs/rules/comma-dangle
2018-08-01 08:38:04 +12:00
chris48s
241cac7100 Fix [circleci] badge (#1815)
require all jobs in the build to pass in order for the status to be 'passing'
Closes #1792
2018-07-30 17:14:08 +01:00
Danial
c974b1b931 throw if given invalid version, refactor [apm] (#1785)
* throw if given invalid version

* refactor service

* add test

* fixup

* move service

* split up module

* update test

* add keywords

* remove from all-badge-examples

* update category [license → miscellaneous]

* Error → InvalidResponse

* minor style fix

* InvalidResponse

* reduce some code duplication

* fixup

* update category

* invalid → unparseable json response
2018-07-30 14:46:47 +12:00
Danial
329db7ddab loosely detect semver versions (#1628)
* loosely detect semver versions

* semver loose validity

* add test

* semver compare versions when null

* add comments for loose

* remove console.log, only match semver scheme

* looser version restrictions

* re-sort version tests

comments refered to incorrect test

* add support for pre-release tags

#1682

* support uppercase, lowercase mixed

* make pre-release opt in

* change pre param to object

* add notes
2018-07-27 08:27:48 +12:00
Danial
b216bcc17e Hide left hand of badge if no label (#1585)
* hide left side if no text

* fix whitespace at start of template

* for-the-badge done

* center text

* add logo support

* update snapshot test

* make first - in static badge optional

* add no label support to non static badges

* Add test for label

* update to not allow use of false/0/null

* fixup
2018-07-27 08:27:32 +12:00
Danial
f5fe85cda2 Fix colorB override not working for static badges (#1801) 2018-07-23 18:33:32 -05:00
Danial
6711119bbb update eslint enable object-curly-spacing (#1789)
https://eslint.org/docs/rules/object-curly-spacing
2018-07-22 14:37:47 +12:00
Thaddée Tyl
fd76819c62 Log request data when Travis errors (#1631)
Related: https://sentry.io/shields/shields/issues/503517592/
2018-07-19 19:29:39 -07:00
Danial
6a1f0f60b1 handle malformed url [dynamic-json] (#1782) 2018-07-17 12:50:36 +12:00
Hans Brende
3c594e8bcc fix for invalid [jenkins] tests (#1777)
* fix for invalid [jenkins] tests
2018-07-17 11:43:23 +12:00
chris48s
7de10783fa Deprecate [magnumci bithound] (#1770)
* deprecate Magnum CI badge

* deprecate BitHound badges
2018-07-11 23:30:52 -04:00
Danial
d8cf836264 Add support for rgb, rgba, hsl, hsla, css named colors (#1635)
* add support for rgb, rgb, css named colors

* add support for hsl, hsla & add color-validate

* update makeBadge test, better coverage

* re-add comment

* add comment for supported colors

* dynamic badge gen, remove 'hex'

* add support for 1.0 opacity & fix 101-109

* fix colorscheme tests

* remove extra tests

* add test for negative values

* add test for uppercase & mixed case colors

* fix mixed case/uppercase test

* allow whitespace around color

* update test error messages

* add comments

* add more uppercase test

* update error message

* default to grey/red if invalid color chosen

default colorscheme:
colorA: grey
colorB: red

* Revert "default to grey/red if invalid color chosen"

This reverts commit 10db0c6d74.
Reverted as this affects the CLI version/when no color specified.

* validColor -> isCSSColor

* assignColor function

* update tests to use sazerac
2018-07-12 10:26:17 +12:00
Stanley Ng
85dd5f0809 Add [Jenkins] Jacoco coverage badge ☘ (#1593)
* Add Jenkins Jacoco coverage badge

* [Jenkins] add service test for jacoco coverage

* Added Jenkins Coverage (Jacoco) in all-badge-examples page

* Defined variables using let/const instead of var

* Used template string for the uri

* Used checkErrorResponse helper function for the error check

* Used NaN method for not a number test

* Prefixed the original Jenkin coverage test with "cobertura:"

* Moved the happy test case at front

* Merge the business logic between jacoco and cobertura

* Fixed lint issue

* Trigger notification
2018-07-10 18:12:26 +12:00
chris48s
036b191996 fix ansible galaxy role name badge (#1763) 2018-07-08 12:50:31 +01:00
chris48s
dc8bc9c5b4 update [bitrise] URL (#1764) 2018-07-08 12:50:19 +01:00