Compare commits

..

108 Commits

Author SHA1 Message Date
release[bot]
0fb13225ba Update Changelog 2023-08-01 18:16:05 +00:00
chris48s
2585590e42 fixup 2023-08-01 19:13:57 +01:00
chris48s
22051db1d2 fix 'draft release' action part 2 2023-08-01 19:05:32 +01:00
chris48s
b428490db4 fix 'draft release' action (#9432) 2023-08-01 18:59:57 +01:00
chris48s
57c2ba0d68 Convert examples arrays to openApi objects (part 1) (#9320)
* add helper functions for generating Open API path/query params with defaults

* tweak Open API schema

- make description optional
- allow null example + allowEmptyValue (for boolean query params)

* convert examples --> openApi in amo

* convert examples --> openApi in ansible

* convert examples --> openApi in appveyor build/job

* add re-usable Open API query param for test-results badges

we can use these for all the 'test results' badges

* convert examples --> openApi in appveyor tests

* DRY up existing dynamic/endpoint param definitions

* DRY up queryParam

* allow enum param in serviceDefinition schema

* improve misleading param name

* check route and openApi are consistent on service load

* fix mistake in ansible role route

* documentation --> description

* add pathParams and queryParams helpers +docstrings

* give everything a search-friendly summary, check for duplicate summary

* prettier fixup
2023-07-31 12:22:33 +01:00
chris48s
1bfda7a54b add a blog post about GH Tag/Release filter param (#9424)
* add a blog post about GH Tag/Release filter param

* Update frontend/blog/2023-07-29-tag-filter.md

Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>

---------

Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>
2023-07-31 12:21:55 +01:00
chris48s
631ca1ccb6 add some tests for [docsrs] (#9423) 2023-07-31 03:06:20 +00:00
Nemo157
2e2959a12c Migrate from docs.rs' builds API to status API (#9422) 2023-07-30 16:01:50 +00:00
dependabot[bot]
fcb83cacec chore(deps-dev): bump eslint-plugin-jsdoc from 46.4.4 to 46.4.5 (#9414)
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 46.4.4 to 46.4.5.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v46.4.4...v46.4.5)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 19:31:59 +00:00
dependabot[bot]
398565d780 chore(deps-dev): bump c8 from 8.0.0 to 8.0.1 (#9412)
Bumps [c8](https://github.com/bcoe/c8) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/bcoe/c8/releases)
- [Changelog](https://github.com/bcoe/c8/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bcoe/c8/compare/v8.0.0...v8.0.1)

---
updated-dependencies:
- dependency-name: c8
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 19:29:58 +00:00
dependabot[bot]
c2fc381449 chore(deps): bump simple-icons from 9.6.0 to 9.7.0 (#9421)
Bumps [simple-icons](https://github.com/simple-icons/simple-icons) from 9.6.0 to 9.7.0.
- [Release notes](https://github.com/simple-icons/simple-icons/releases)
- [Commits](https://github.com/simple-icons/simple-icons/compare/9.6.0...9.7.0)

---
updated-dependencies:
- dependency-name: simple-icons
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 19:23:24 +00:00
dependabot[bot]
c7e842cd3a chore(deps-dev): bump eslint-plugin-import from 2.27.5 to 2.28.0 (#9416)
Bumps [eslint-plugin-import](https://github.com/import-js/eslint-plugin-import) from 2.27.5 to 2.28.0.
- [Release notes](https://github.com/import-js/eslint-plugin-import/releases)
- [Changelog](https://github.com/import-js/eslint-plugin-import/blob/main/CHANGELOG.md)
- [Commits](https://github.com/import-js/eslint-plugin-import/compare/v2.27.5...v2.28.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-import
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 19:11:17 +00:00
dependabot[bot]
66225a62f6 chore(deps-dev): bump eslint-config-prettier from 8.8.0 to 8.9.0 (#9415)
Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 8.8.0 to 8.9.0.
- [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/eslint-config-prettier/compare/v8.8.0...v8.9.0)

---
updated-dependencies:
- dependency-name: eslint-config-prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 19:11:03 +00:00
dependabot[bot]
943ee3ca23 chore(deps-dev): bump danger from 11.2.6 to 11.2.7 (#9417)
Bumps [danger](https://github.com/danger/danger-js) from 11.2.6 to 11.2.7.
- [Release notes](https://github.com/danger/danger-js/releases)
- [Changelog](https://github.com/danger/danger-js/blob/main/CHANGELOG.md)
- [Commits](https://github.com/danger/danger-js/compare/11.2.6...11.2.7)

---
updated-dependencies:
- dependency-name: danger
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 19:08:48 +00:00
dependabot[bot]
ff98bb6365 chore(deps): bump @sentry/node from 7.60.0 to 7.60.1 (#9418)
Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.60.0 to 7.60.1.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.60.0...7.60.1)

---
updated-dependencies:
- dependency-name: "@sentry/node"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 19:08:12 +00:00
dependabot[bot]
5e585c364e chore(deps-dev): bump simple-git-hooks from 2.8.1 to 2.9.0 (#9419)
Bumps [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks) from 2.8.1 to 2.9.0.
- [Release notes](https://github.com/toplenboren/simple-git-hooks/releases)
- [Changelog](https://github.com/toplenboren/simple-git-hooks/blob/master/Changelog.md)
- [Commits](https://github.com/toplenboren/simple-git-hooks/compare/2.8.1...2.9.0)

---
updated-dependencies:
- dependency-name: simple-git-hooks
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 19:07:55 +00:00
dependabot[bot]
e7294845c7 chore(deps-dev): bump @typescript-eslint/parser from 6.1.0 to 6.2.0 (#9420)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.1.0 to 6.2.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.2.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-28 19:07:05 +00:00
chris48s
c7efb27086 exclude assets dir from raster redirects (#9409) 2023-07-24 13:15:05 +01:00
chris48s
d882433fd9 move some docs to the website (#9347)
* move some docs to the website

* update expected test value

* link to new documentation locations
2023-07-24 12:20:43 +01:00
empathicqubit
436f3a1a3f [OpenVSX] Fix OpenVSX API call for unversioned package URLs (#9408) 2023-07-23 09:39:43 +00:00
dependabot[bot]
ef2649bd4b chore(deps-dev): bump eslint-plugin-react from 7.32.2 to 7.33.0 (#9395)
* chore(deps-dev): bump eslint-plugin-react from 7.32.2 to 7.33.0

Bumps [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) from 7.32.2 to 7.33.0.
- [Release notes](https://github.com/jsx-eslint/eslint-plugin-react/releases)
- [Changelog](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jsx-eslint/eslint-plugin-react/compare/v7.32.2...v7.33.0)

---
updated-dependencies:
- dependency-name: eslint-plugin-react
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix for new lint rules

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: chris48s <git@chris-shaw.dev>
2023-07-23 09:34:54 +00:00
dependabot[bot]
d5c1bdc8ec chore(deps-dev): bump clsx from 1.2.1 to 2.0.0 (#9403)
Bumps [clsx](https://github.com/lukeed/clsx) from 1.2.1 to 2.0.0.
- [Release notes](https://github.com/lukeed/clsx/releases)
- [Commits](https://github.com/lukeed/clsx/compare/v1.2.1...v2.0.0)

---
updated-dependencies:
- dependency-name: clsx
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 20:14:46 +00:00
dependabot[bot]
3dfef0011c chore(deps): bump simple-icons from 9.5.0 to 9.6.0 (#9401)
Bumps [simple-icons](https://github.com/simple-icons/simple-icons) from 9.5.0 to 9.6.0.
- [Release notes](https://github.com/simple-icons/simple-icons/releases)
- [Commits](https://github.com/simple-icons/simple-icons/compare/9.5.0...9.6.0)

---
updated-dependencies:
- dependency-name: simple-icons
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:53:02 +00:00
dependabot[bot]
df436b17a6 chore(deps): bump fast-xml-parser from 4.2.5 to 4.2.6 (#9404)
Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 4.2.5 to 4.2.6.
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.2.5...v4.2.6)

---
updated-dependencies:
- dependency-name: fast-xml-parser
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:52:12 +00:00
dependabot[bot]
8880ec5171 chore(deps): bump @xmldom/xmldom from 0.8.9 to 0.8.10 (#9397)
Bumps [@xmldom/xmldom](https://github.com/xmldom/xmldom) from 0.8.9 to 0.8.10.
- [Release notes](https://github.com/xmldom/xmldom/releases)
- [Changelog](https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/xmldom/xmldom/compare/0.8.9...0.8.10)

---
updated-dependencies:
- dependency-name: "@xmldom/xmldom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:51:56 +00:00
dependabot[bot]
ad873fb8db chore(deps): bump pretty-bytes from 6.1.0 to 6.1.1 (#9399)
Bumps [pretty-bytes](https://github.com/sindresorhus/pretty-bytes) from 6.1.0 to 6.1.1.
- [Release notes](https://github.com/sindresorhus/pretty-bytes/releases)
- [Commits](https://github.com/sindresorhus/pretty-bytes/compare/v6.1.0...v6.1.1)

---
updated-dependencies:
- dependency-name: pretty-bytes
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:51:53 +00:00
dependabot[bot]
3c4f913f75 chore(deps): bump word-wrap from 1.2.3 to 1.2.5 (#9406)
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.5.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.5)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:38:07 +00:00
dependabot[bot]
f0f2dd74d6 chore(deps): bump @sentry/node from 7.58.1 to 7.60.0 (#9396)
Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.58.1 to 7.60.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.58.1...7.60.0)

---
updated-dependencies:
- dependency-name: "@sentry/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:35:51 +00:00
dependabot[bot]
cbcad6dd4e chore(deps-dev): bump eslint from 8.44.0 to 8.45.0 (#9398)
Bumps [eslint](https://github.com/eslint/eslint) from 8.44.0 to 8.45.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.44.0...v8.45.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:35:22 +00:00
dependabot[bot]
c8ec665493 chore(deps-dev): bump cypress from 12.17.1 to 12.17.2 (#9402)
Bumps [cypress](https://github.com/cypress-io/cypress) from 12.17.1 to 12.17.2.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cypress-io/cypress/compare/v12.17.1...v12.17.2)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:32:57 +00:00
dependabot[bot]
f84de2788a chore(deps-dev): bump @typescript-eslint/parser from 6.0.0 to 6.1.0 (#9400)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 6.0.0 to 6.1.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.1.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:32:40 +00:00
dependabot[bot]
398288b86c chore(deps-dev): bump eslint-plugin-jsdoc from 46.4.3 to 46.4.4 (#9394)
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 46.4.3 to 46.4.4.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v46.4.3...v46.4.4)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-22 19:32:25 +00:00
jNullj
af7b7f3597 devops: automate bug report tests (#9386)
* devops: automate bug report tests

Devs run `npm run badge` often when getting a bug report for shields.io service.
This PR automates this tests so the maintainer can get test results automaticly when getting into a new ticket.
Add test-bug-run-badge.yml workflow for github actions automation.

Will only run if bug has the 'qeustion' label added by bug reporting template. And will only setup enviorment and perform the test if the link provided in the issue is valid and the issue is related to shields.io.
Link to job results is sent as a new comment on the issue.

Resolves #9351

* remove secrets to avoid secret leak

* change stage name

* remove unused id
2023-07-22 19:18:18 +00:00
Kavin
528165f65c Add support for [Lemmy] (#9368)
* Add support for Lemmy.

* Add tests for lemmy.

* Remove specifying a server fqdn to fetch from.

* Fix for requested changes.
2023-07-17 15:53:58 +00:00
chris48s
f84ccb24ae upgrade to npm 9 (#9323) 2023-07-16 15:07:20 +01:00
dependabot[bot]
667dd43cf4 chore(deps-dev): bump @typescript-eslint/parser from 5.61.0 to 6.0.0 (#9384)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.61.0 to 6.0.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v6.0.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:46:12 +00:00
dependabot[bot]
9a698a85a9 chore(deps-dev): bump nock from 13.3.1 to 13.3.2 (#9380)
Bumps [nock](https://github.com/nock/nock) from 13.3.1 to 13.3.2.
- [Release notes](https://github.com/nock/nock/releases)
- [Changelog](https://github.com/nock/nock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/nock/nock/compare/v13.3.1...v13.3.2)

---
updated-dependencies:
- dependency-name: nock
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:42:53 +00:00
dependabot[bot]
7d2bb7f51d chore(deps): bump semver from 7.5.3 to 7.5.4 (#9375)
Bumps [semver](https://github.com/npm/node-semver) from 7.5.3 to 7.5.4.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.5.3...v7.5.4)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:41:40 +00:00
dependabot[bot]
4f5c40d12a chore(deps-dev): bump nodemon from 2.0.22 to 3.0.1 (#9377)
Bumps [nodemon](https://github.com/remy/nodemon) from 2.0.22 to 3.0.1.
- [Release notes](https://github.com/remy/nodemon/releases)
- [Commits](https://github.com/remy/nodemon/compare/v2.0.22...v3.0.1)

---
updated-dependencies:
- dependency-name: nodemon
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:34:45 +00:00
dependabot[bot]
819500354c chore(deps): bump @sentry/node from 7.57.0 to 7.58.1 (#9381)
Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.57.0 to 7.58.1.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.57.0...7.58.1)

---
updated-dependencies:
- dependency-name: "@sentry/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:27:16 +00:00
dependabot[bot]
a1b613fbd4 chore(deps-dev): bump cypress from 12.17.0 to 12.17.1 (#9379)
Bumps [cypress](https://github.com/cypress-io/cypress) from 12.17.0 to 12.17.1.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cypress-io/cypress/compare/v12.17.0...v12.17.1)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:26:54 +00:00
dependabot[bot]
27644c9862 chore(deps): bump xpath from 0.0.32 to 0.0.33 (#9382)
Bumps [xpath](https://github.com/goto100/xpath) from 0.0.32 to 0.0.33.
- [Commits](https://github.com/goto100/xpath/commits)

---
updated-dependencies:
- dependency-name: xpath
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:24:12 +00:00
dependabot[bot]
b0e8fe0084 chore(deps): bump @xmldom/xmldom from 0.8.8 to 0.8.9 (#9373)
Bumps [@xmldom/xmldom](https://github.com/xmldom/xmldom) from 0.8.8 to 0.8.9.
- [Release notes](https://github.com/xmldom/xmldom/releases)
- [Changelog](https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/xmldom/xmldom/compare/0.8.8...0.8.9)

---
updated-dependencies:
- dependency-name: "@xmldom/xmldom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:23:55 +00:00
dependabot[bot]
f0e5ad2d3c chore(deps): bump simple-icons from 9.4.0 to 9.5.0 (#9378)
Bumps [simple-icons](https://github.com/simple-icons/simple-icons) from 9.4.0 to 9.5.0.
- [Release notes](https://github.com/simple-icons/simple-icons/releases)
- [Commits](https://github.com/simple-icons/simple-icons/compare/9.4.0...9.5.0)

---
updated-dependencies:
- dependency-name: simple-icons
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:13:03 +00:00
dependabot[bot]
d00659e42b chore(deps): bump glob from 10.3.1 to 10.3.3 (#9376)
Bumps [glob](https://github.com/isaacs/node-glob) from 10.3.1 to 10.3.3.
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v10.3.1...v10.3.3)

---
updated-dependencies:
- dependency-name: glob
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:12:45 +00:00
dependabot[bot]
5e963a48f3 chore(deps-dev): bump mocha-junit-reporter from 2.2.0 to 2.2.1 (#9383)
Bumps [mocha-junit-reporter](https://github.com/michaelleeallen/mocha-junit-reporter) from 2.2.0 to 2.2.1.
- [Release notes](https://github.com/michaelleeallen/mocha-junit-reporter/releases)
- [Commits](https://github.com/michaelleeallen/mocha-junit-reporter/compare/v2.2.0...v2.2.1)

---
updated-dependencies:
- dependency-name: mocha-junit-reporter
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-14 17:03:51 +00:00
chris48s
40f2b9e1a7 run service/docker builds on merge queue builds (#8943) 2023-07-14 17:25:19 +01:00
dependabot[bot]
13fd752ada chore(deps-dev): bump prism-react-renderer from 1.3.5 to 2.0.6 (#9328)
* chore(deps-dev): bump prism-react-renderer from 1.3.5 to 2.0.6

Bumps [prism-react-renderer](https://github.com/FormidableLabs/prism-react-renderer) from 1.3.5 to 2.0.6.
- [Release notes](https://github.com/FormidableLabs/prism-react-renderer/releases)
- [Commits](https://github.com/FormidableLabs/prism-react-renderer/compare/v1.3.5...prism-react-renderer@2.0.6)

---
updated-dependencies:
- dependency-name: prism-react-renderer
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* update for backwards-incompatible changes

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: chris48s <git@chris-shaw.dev>
2023-07-14 17:04:31 +01:00
Pierre-Yves Bigourdan
e7fc6d56d3 Go back to default YouTube cache (#9372) 2023-07-14 15:42:50 +01:00
chris48s
83c22ccd55 cache docker badges for longer (take 3) (#9369) 2023-07-12 20:28:05 +01:00
chris48s
ffcce04deb edit comment about styles to remove in future (#9363) 2023-07-10 16:39:16 +01:00
dependabot[bot]
b9d96755ec chore(deps-dev): bump prettier from 2.8.8 to 3.0.0 (#9357)
* chore(deps-dev): bump prettier from 2.8.8 to 3.0.0

Bumps [prettier](https://github.com/prettier/prettier) from 2.8.8 to 3.0.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prettier/prettier/compare/2.8.8...3.0.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* reformat all the things (prettier 3)

* update tests to await calls to prettier.format()

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: chris48s <git@chris-shaw.dev>
2023-07-10 09:27:51 +00:00
chris48s
fb794ec479 Revert "[OpenCollective] update opencollective to api v2 (#9346)" (#9362)
This reverts commit e02c8aa884.
2023-07-08 13:13:06 +01:00
dependabot[bot]
5ff782219b chore(deps): bump simple-icons from 9.3.0 to 9.4.0 (#9352)
Bumps [simple-icons](https://github.com/simple-icons/simple-icons) from 9.3.0 to 9.4.0.
- [Release notes](https://github.com/simple-icons/simple-icons/releases)
- [Commits](https://github.com/simple-icons/simple-icons/compare/9.3.0...9.4.0)

---
updated-dependencies:
- dependency-name: simple-icons
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-08 12:42:49 +01:00
dependabot[bot]
b28b4d6414 chore(deps-dev): bump cypress from 12.16.0 to 12.17.0 (#9353)
Bumps [cypress](https://github.com/cypress-io/cypress) from 12.16.0 to 12.17.0.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cypress-io/cypress/compare/v12.16.0...v12.17.0)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-08 11:31:53 +00:00
dependabot[bot]
877cf628a6 chore(deps-dev): bump @typescript-eslint/parser from 5.60.1 to 5.61.0 (#9354)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.60.1 to 5.61.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.61.0/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-08 11:23:08 +00:00
dependabot[bot]
f2cafb8464 chore(deps): bump dayjs from 1.11.8 to 1.11.9 (#9355)
Bumps [dayjs](https://github.com/iamkun/dayjs) from 1.11.8 to 1.11.9.
- [Release notes](https://github.com/iamkun/dayjs/releases)
- [Changelog](https://github.com/iamkun/dayjs/blob/v1.11.9/CHANGELOG.md)
- [Commits](https://github.com/iamkun/dayjs/compare/v1.11.8...v1.11.9)

---
updated-dependencies:
- dependency-name: dayjs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-08 11:15:29 +00:00
dependabot[bot]
2cad636f6f chore(deps-dev): bump eslint from 8.43.0 to 8.44.0 (#9356)
Bumps [eslint](https://github.com/eslint/eslint) from 8.43.0 to 8.44.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v8.43.0...v8.44.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-08 11:07:28 +00:00
dependabot[bot]
749d05cf9d chore(deps-dev): bump eslint-plugin-jsdoc from 46.4.2 to 46.4.3 (#9358)
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 46.4.2 to 46.4.3.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v46.4.2...v46.4.3)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-08 10:59:57 +00:00
chris48s
71cd657e3c improve docs for github issues search badge (#9360)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-08 10:52:03 +00:00
xxchan
e02c8aa884 [OpenCollective] update opencollective to api v2 (#9346)
* update opencollective to api v2

* fix tests

* fix: do not filter by accountType for opencollective/all

* remove 404

* remove required in schema

* cnt -> count

* keep by-tier code as-is

---------

Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-08 10:18:02 +00:00
jNullj
1251adaec2 Add [GitHubDiscussionsSearch] and GitHubRepoDiscussionsSearch service (#9340)
* Add GitHub Discussions custom search service

This commit adds a GitHub Discussions custom search service in the github-discussions-custom-search.service.js file. It includes classes for global discussions search (GithubDiscussionsSearch) and repository-specific discussions search (GithubRepoDiscussionsSearch). Users can now search discussions with custom queries and retrieve the discussion count.

Fixes #9213

* Add tester to GithubDiscussionsSearch

* Add documentation for GithubDiscussionsSearch

Inform users of filters and query values for the free search.

* Update GithubDiscussionsSearch examples

Change examples from filter by author to `filter` by `answered-by` as this has higher change of being a more common use case.

* fix typo

---------

Co-authored-by: jNullj <jNullj@users.noreply.github.com>
Co-authored-by: chris48s <chris48s@users.noreply.github.com>
2023-07-07 20:30:16 +00:00
chris48s
1543d0f363 Allow user to filter github tags and releases (#9193)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-03 20:27:31 +00:00
chris48s
e7197f6db4 don't URL encode slash in [githubactionsworkflow] badge (#9322)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-03 20:01:13 +00:00
chris48s
9fafb3110c add a bit of border to select boxes (#9348)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-03 17:09:24 +00:00
chris48s
7bad3f5902 deprecate [snyk] badges (#9349)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-03 16:59:04 +00:00
chris48s
1afa3b7871 increase max-age on [docker] badges, again (#9350) 2023-07-03 11:48:50 -05:00
github-actions[bot]
c37dd08349 Changelog for Release server-2023-07-02 (#9344)
* Update Changelog

* Update CHANGELOG.md

---------

Co-authored-by: release[bot] <actions@users.noreply.github.com>
Co-authored-by: chris48s <chris48s@users.noreply.github.com>
2023-07-02 09:59:38 +00:00
chris48s
bf0395dc00 cache [dockerpulls] badges for an hour (#9343) 2023-07-02 10:25:57 +01:00
dependabot[bot]
547e528ba7 chore(deps-dev): bump lint-staged from 13.2.2 to 13.2.3 (#9331)
Bumps [lint-staged](https://github.com/okonet/lint-staged) from 13.2.2 to 13.2.3.
- [Release notes](https://github.com/okonet/lint-staged/releases)
- [Commits](https://github.com/okonet/lint-staged/compare/v13.2.2...v13.2.3)

---
updated-dependencies:
- dependency-name: lint-staged
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-02 09:16:34 +00:00
dependabot[bot]
037a77ec23 chore(deps): bump chalk from 5.2.0 to 5.3.0 (#9332)
Bumps [chalk](https://github.com/chalk/chalk) from 5.2.0 to 5.3.0.
- [Release notes](https://github.com/chalk/chalk/releases)
- [Commits](https://github.com/chalk/chalk/compare/v5.2.0...v5.3.0)

---
updated-dependencies:
- dependency-name: chalk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-01 21:09:12 +00:00
dependabot[bot]
dbb993e270 chore(deps-dev): bump eslint-plugin-jsdoc from 46.2.6 to 46.4.2 (#9335)
Bumps [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) from 46.2.6 to 46.4.2.
- [Release notes](https://github.com/gajus/eslint-plugin-jsdoc/releases)
- [Changelog](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/.releaserc)
- [Commits](https://github.com/gajus/eslint-plugin-jsdoc/compare/v46.2.6...v46.4.2)

---
updated-dependencies:
- dependency-name: eslint-plugin-jsdoc
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-01 20:59:01 +00:00
dependabot[bot]
dc36aeffdb chore(deps): bump simple-icons from 9.2.0 to 9.3.0 (#9330)
Bumps [simple-icons](https://github.com/simple-icons/simple-icons) from 9.2.0 to 9.3.0.
- [Release notes](https://github.com/simple-icons/simple-icons/releases)
- [Commits](https://github.com/simple-icons/simple-icons/compare/9.2.0...9.3.0)

---
updated-dependencies:
- dependency-name: simple-icons
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-01 21:52:29 +01:00
dependabot[bot]
ef8e9cc31f chore(deps): bump glob from 10.3.0 to 10.3.1 (#9333)
Bumps [glob](https://github.com/isaacs/node-glob) from 10.3.0 to 10.3.1.
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v10.3.0...v10.3.1)

---
updated-dependencies:
- dependency-name: glob
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-01 20:45:04 +00:00
dependabot[bot]
2cad078b66 chore(deps): bump @sentry/node from 7.56.0 to 7.57.0 (#9334)
Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.56.0 to 7.57.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.56.0...7.57.0)

---
updated-dependencies:
- dependency-name: "@sentry/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-01 20:35:18 +00:00
dependabot[bot]
eb7d3bcad4 chore(deps): bump pg from 8.11.0 to 8.11.1 (#9337)
Bumps [pg](https://github.com/brianc/node-postgres/tree/HEAD/packages/pg) from 8.11.0 to 8.11.1.
- [Changelog](https://github.com/brianc/node-postgres/blob/master/CHANGELOG.md)
- [Commits](https://github.com/brianc/node-postgres/commits/pg@8.11.1/packages/pg)

---
updated-dependencies:
- dependency-name: pg
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-01 20:02:03 +00:00
dependabot[bot]
7aeb481eed chore(deps-dev): bump @typescript-eslint/parser from 5.59.9 to 5.60.1 (#9336)
Bumps [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) from 5.59.9 to 5.60.1.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v5.60.1/packages/parser)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/parser"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-01 19:53:27 +00:00
dependabot[bot]
80e27a7a04 chore(deps-dev): bump cypress from 12.15.0 to 12.16.0 (#9329)
Bumps [cypress](https://github.com/cypress-io/cypress) from 12.15.0 to 12.16.0.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cypress-io/cypress/compare/v12.15.0...v12.16.0)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-07-01 19:45:06 +00:00
Pierre-Yves Bigourdan
04a6344efe Mention YouTube API services and link to Google Privacy Policy (#9339) 2023-07-01 11:20:25 +00:00
chris48s
640cd5643e add a bit of border to text boxes (#9324)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-27 19:58:31 +00:00
chris48s
53cce8f1f1 allow negative timestamps in relative [date] badge (#9321)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-26 22:34:20 +00:00
LitoMore
c47f93219b Adjust deploy-review-app script (#9317) 2023-06-26 19:20:34 +00:00
dependabot[bot]
53efe52801 chore(deps): bump fast-xml-parser from 4.2.4 to 4.2.5 (#9311)
Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) from 4.2.4 to 4.2.5.
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.2.4...v4.2.5)

---
updated-dependencies:
- dependency-name: fast-xml-parser
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-23 21:20:51 +01:00
dependabot[bot]
cdf6317f14 chore(deps): bump graphql from 15.8.0 to 16.7.1 (#9309)
Bumps [graphql](https://github.com/graphql/graphql-js) from 15.8.0 to 16.7.1.
- [Release notes](https://github.com/graphql/graphql-js/releases)
- [Commits](https://github.com/graphql/graphql-js/compare/v15.8.0...v16.7.1)

---
updated-dependencies:
- dependency-name: graphql
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-23 20:11:19 +00:00
dependabot[bot]
3d04209405 chore(deps): bump glob from 10.2.7 to 10.3.0 (#9307)
Bumps [glob](https://github.com/isaacs/node-glob) from 10.2.7 to 10.3.0.
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v10.2.7...v10.3.0)

---
updated-dependencies:
- dependency-name: glob
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-23 20:02:06 +00:00
dependabot[bot]
c2b379f1f5 chore(deps): bump simple-icons from 9.1.0 to 9.2.0 (#9312)
Bumps [simple-icons](https://github.com/simple-icons/simple-icons) from 9.1.0 to 9.2.0.
- [Release notes](https://github.com/simple-icons/simple-icons/releases)
- [Commits](https://github.com/simple-icons/simple-icons/compare/9.1.0...9.2.0)

---
updated-dependencies:
- dependency-name: simple-icons
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-23 20:53:32 +01:00
dependabot[bot]
75eb794945 chore(deps): bump semver from 7.5.2 to 7.5.3 (#9304)
Bumps [semver](https://github.com/npm/node-semver) from 7.5.2 to 7.5.3.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.5.2...v7.5.3)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-23 19:24:28 +00:00
dependabot[bot]
a5b816760b chore(deps-dev): bump cypress from 12.14.0 to 12.15.0 (#9310)
Bumps [cypress](https://github.com/cypress-io/cypress) from 12.14.0 to 12.15.0.
- [Release notes](https://github.com/cypress-io/cypress/releases)
- [Changelog](https://github.com/cypress-io/cypress/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/cypress-io/cypress/compare/v12.14.0...v12.15.0)

---
updated-dependencies:
- dependency-name: cypress
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-23 19:16:52 +00:00
dependabot[bot]
c0d6fa699d chore(deps-dev): bump sinon from 15.1.2 to 15.2.0 (#9305)
Bumps [sinon](https://github.com/sinonjs/sinon) from 15.1.2 to 15.2.0.
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md)
- [Commits](https://github.com/sinonjs/sinon/compare/v15.1.2...v15.2.0)

---
updated-dependencies:
- dependency-name: sinon
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-23 19:07:21 +00:00
dependabot[bot]
4a03b86300 chore(deps): bump @sentry/node from 7.55.2 to 7.56.0 (#9306)
Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.55.2 to 7.56.0.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.55.2...7.56.0)

---
updated-dependencies:
- dependency-name: "@sentry/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-23 18:58:59 +00:00
chris48s
9137b46bc3 temp fix: wrap code examples tabs in narrow browser windows (#9302) 2023-06-23 19:48:17 +01:00
chris48s
1e85cf7926 upgrade to graphql 16 (#9290)
* upgrade to graphql 16

* update base graphql tests
2023-06-23 19:47:40 +01:00
LitoMore
5085ef0209 chore(frontend): open homepage feature links in new tab (#9300)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-19 14:15:14 +00:00
chris48s
86f0a86094 adapt opencollective images to theme background (#9298) 2023-06-19 14:58:00 +01:00
chris48s
6f78e6f81d run package tests on node 20 (#9293)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 20:06:55 +00:00
chris48s
a2ca06e033 try running tests on node 18 (#9292)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 19:57:38 +00:00
chris48s
08e6933f0e Upgrade to ESLint 8; affects [docker factorio] (#9289)
* upgrade to ESLint 8

* update services to fix camelcase rule errors

---------

Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 19:47:18 +00:00
chris48s
e7737ce050 remove obsolete travis .org examples (#9284)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 12:00:36 +00:00
chris48s
f24b00fecd increase max age on reddit badges (#9282)
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 11:50:19 +00:00
dependabot[bot]
1c64ec6528 chore(deps): bump semver from 7.5.1 to 7.5.2 (#9260)
Bumps [semver](https://github.com/npm/node-semver) from 7.5.1 to 7.5.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.5.1...v7.5.2)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 09:55:22 +00:00
chris48s
30377f6f33 set a sensible meta description (#9283) 2023-06-18 10:44:26 +01:00
dependabot[bot]
4dc6f51650 chore(deps-dev): bump sinon from 15.1.0 to 15.1.2 (#9262)
Bumps [sinon](https://github.com/sinonjs/sinon) from 15.1.0 to 15.1.2.
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/main/docs/changelog.md)
- [Commits](https://github.com/sinonjs/sinon/compare/v15.1.0...v15.1.2)

---
updated-dependencies:
- dependency-name: sinon
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 09:24:16 +00:00
dependabot[bot]
2b881f330d chore(deps): bump simple-icons from 9.0.0 to 9.1.0 (#9271)
Bumps [simple-icons](https://github.com/simple-icons/simple-icons) from 9.0.0 to 9.1.0.
- [Release notes](https://github.com/simple-icons/simple-icons/releases)
- [Commits](https://github.com/simple-icons/simple-icons/compare/9.0.0...9.1.0)

---
updated-dependencies:
- dependency-name: simple-icons
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 08:47:06 +00:00
dependabot[bot]
c6f157b7ef chore(deps-dev): bump url from 0.11.0 to 0.11.1 (#9269)
Bumps [url](https://github.com/defunctzombie/node-url) from 0.11.0 to 0.11.1.
- [Commits](https://github.com/defunctzombie/node-url/compare/v0.11.0...v0.11.1)

---
updated-dependencies:
- dependency-name: url
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 08:38:26 +00:00
dependabot[bot]
86de4190e4 chore(deps-dev): bump @easyops-cn/docusaurus-search-local (#9277)
Bumps [@easyops-cn/docusaurus-search-local](https://github.com/easyops-cn/docusaurus-search-local) from 0.33.6 to 0.35.0.
- [Release notes](https://github.com/easyops-cn/docusaurus-search-local/releases)
- [Changelog](https://github.com/easyops-cn/docusaurus-search-local/blob/master/docusaurus-search-local/CHANGELOG.md)
- [Commits](https://github.com/easyops-cn/docusaurus-search-local/compare/v0.33.6...v0.35.0)

---
updated-dependencies:
- dependency-name: "@easyops-cn/docusaurus-search-local"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 08:30:26 +00:00
dependabot[bot]
dad1e43532 chore(deps-dev): bump c8 from 7.14.0 to 8.0.0 (#9272)
Bumps [c8](https://github.com/bcoe/c8) from 7.14.0 to 8.0.0.
- [Release notes](https://github.com/bcoe/c8/releases)
- [Changelog](https://github.com/bcoe/c8/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bcoe/c8/compare/v7.14.0...v8.0.0)

---
updated-dependencies:
- dependency-name: c8
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 08:23:07 +00:00
dependabot[bot]
3fe013eec3 chore(deps): bump @sentry/node from 7.54.0 to 7.55.2 (#9261)
Bumps [@sentry/node](https://github.com/getsentry/sentry-javascript) from 7.54.0 to 7.55.2.
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/7.54.0...7.55.2)

---
updated-dependencies:
- dependency-name: "@sentry/node"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
2023-06-18 08:14:16 +00:00
chris48s
a5f91a40e5 fix a load of spacing issues in frontend content (#9281) 2023-06-18 09:05:42 +01:00
587 changed files with 4572 additions and 24732 deletions

View File

@@ -12,7 +12,7 @@ body:
**fetch and display data from an upstream service**.
If your suggestion is for a static badge
(which shows the same information every time it is requested), it is
[already possible to make these](https://github.com/badges/shields/blob/master/doc/static-badges.md).
[already possible to make these](https://shields.io/docs/static-badges).
We don't add specific routes for badges which only show static information.
- type: textarea
@@ -25,7 +25,7 @@ body:
- Which service is this badge for e.g: GitHub, Travis CI
- What sort of information should this badge show?
Provide an example in plain text e.g: "version | v1.01" or as a static badge
(static badge generator can be found at https://shields.io/#your-badge )
(static badge generator can be found at https://shields.io/badges/static-badge )
validations:
required: true

View File

@@ -28,7 +28,7 @@ function allChangelogLinesAreVersionBump(changelogLines) {
changelogLines.length > 0 &&
changelogLines.length ===
changelogLines.filter(line =>
line.includes('Version bump only for package')
line.includes('Version bump only for package'),
).length
)
}
@@ -52,14 +52,15 @@ function isPointlessVersionBump(body) {
.filter(line => !line.startsWith('<h'))
.filter(line => !line.startsWith('<p>All notable changes'))
.filter(
line => !line.startsWith('See <a href="https://conventionalcommits.org">')
line =>
!line.startsWith('See <a href="https://conventionalcommits.org">'),
)
.filter(line => !line.startsWith('<!--'))
.filter(
line =>
!line.startsWith(
'<p><a href="https://www.gatsbyjs.com/docs/reference/release-notes/'
)
'<p><a href="https://www.gatsbyjs.com/docs/reference/release-notes/',
),
)
return allChangelogLinesAreVersionBump(changelogLines)
}

View File

@@ -1,4 +1,4 @@
FROM node:12-buster
FROM node:18-bullseye
RUN apt-get update
RUN apt-get install -y jq

View File

@@ -2,14 +2,17 @@
set -euxo pipefail
# Set up a git user
git config user.name "release[bot]"
git config user.email "actions@users.noreply.github.com"
# mark workspace dir as 'safe'
git config --system --add safe.directory '/github/workspace'
# Find last server-YYYY-MM-DD tag
git fetch --unshallow --tags
LAST_TAG=$(git tag | grep server | tail -n 1)
# Set up a git user
git config user.name "release[bot]"
git config user.email "actions@users.noreply.github.com"
# Find the marker in CHANGELOG.md
INSERT_POINT=$(grep -n "^\-\-\-$" CHANGELOG.md | cut -f1 -d:)
INSERT_POINT=$((INSERT_POINT+1))

View File

@@ -19,6 +19,10 @@ runs:
with:
node-version: ${{ inputs.node-version }}
- name: Install NPM 9
run: npm install -g npm@^9.0.0
shell: bash
- name: Install dependencies
if: ${{ inputs.cypress == 'false' }}
env:

View File

@@ -10,12 +10,11 @@ org="shields-io"
# This will fail if $PR_NUMBER is not a valid PR
pr_json=$(curl --fail "https://api.github.com/repos/badges/shields/pulls/$PR_NUMBER")
# Attempt to apply the PR diff to the target branch
# This will fail if it does not merge cleanly
# Checkout the PR branch
git config user.name "actions[bot]"
git config user.email "actions@users.noreply.github.com"
git fetch origin "pull/$PR_NUMBER/head:pr-$PR_NUMBER"
git merge "pr-$PR_NUMBER"
git checkout "pr-$PR_NUMBER"
# If the app does not already exist, create it
if ! flyctl status --app "$app"; then

View File

@@ -1,6 +1,9 @@
name: Build Docker Image
on:
pull_request:
push:
branches:
- 'gh-readonly-queue/**'
jobs:
build-docker-image:

View File

@@ -0,0 +1,67 @@
name: Test new bug report badge
run-name: Test bug report on issue ${{ github.event.issue.number }}
on:
issues:
types: [opened]
jobs:
extract-bug-badge-url:
if: ${{ contains(github.event.issue.labels.*.name, 'question') }}
runs-on: ubuntu-latest
outputs:
runBadgeTest: ${{ steps.testCondition.outputs.runNext }}
link: ${{ steps.testCondition.outputs.link }}
steps:
- name: Test badge test run conditions
id: testCondition
run: |
product=$(echo "${{ github.event.issue.body }}" | grep -A2 "Are you experiencing an issue with.*" | tail -n 1)
link=$(echo "${{ github.event.issue.body }}" | grep -A2 "Link to the badge.*" | tail -n 1)
if [[ "$product" == "shields.io" && "$link" == "https://img.shields.io"* ]]; then
echo "runNext=true" >> "$GITHUB_OUTPUT"
echo "link=$link" >> "$GITHUB_OUTPUT"
else
echo "Conditions not met. Skipping the workflow..."
echo "runNext=false" >> "$GITHUB_OUTPUT"
fi
run-bug-badge-url-test:
needs: extract-bug-badge-url
if: needs.extract-bug-badge-url.outputs.runBadgeTest == 'true'
permissions:
issues: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup
uses: ./.github/actions/setup
with:
node-version: 16
cypress: false
- name: Output debug info
env:
TEST_BADGE_LINK: '${{ needs.extract-bug-badge-url.outputs.link }}'
run: npm run badge $TEST_BADGE_LINK
- name: Add Comment to Issue
uses: actions/github-script@v6
with:
script: |
const issueNumber = context.issue.number;
const owner = context.repo.owner;
const repo = context.repo.repo;
const runId = context.runId;
const jobUrl = `https://github.com/${owner}/${repo}/actions/runs/${runId}`;
const issueComment = `
Badge tested using \`npm run badge ${{ needs.extract-bug-badge-url.outputs.link }}\`
Output is available [here](${jobUrl})
`;
github.rest.issues.createComment({
issue_number: issueNumber,
owner: owner,
repo: repo,
body: issueComment
});

View File

@@ -1,4 +1,4 @@
name: Integration@node 17
name: Integration@node 18
on:
pull_request:
types: [opened, reopened, synchronize]
@@ -8,7 +8,7 @@ on:
- 'dependabot/**'
jobs:
test-integration-17:
test-integration-18:
runs-on: ubuntu-latest
env:
PAT_EXISTS: ${{ secrets.GH_PAT != '' }}
@@ -35,7 +35,7 @@ jobs:
- name: Setup
uses: ./.github/actions/setup
with:
node-version: 17
node-version: 18
env:
NPM_CONFIG_ENGINE_STRICT: 'false'

View File

@@ -1,4 +1,4 @@
name: Main@node 17
name: Main@node 18
on:
pull_request:
types: [opened, reopened, synchronize]
@@ -8,7 +8,7 @@ on:
- 'dependabot/**'
jobs:
test-main-17:
test-main-18:
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -17,7 +17,7 @@ jobs:
- name: Setup
uses: ./.github/actions/setup
with:
node-version: 17
node-version: 18
env:
NPM_CONFIG_ENGINE_STRICT: 'false'

View File

@@ -16,12 +16,9 @@ jobs:
strategy:
matrix:
include:
- node: '14'
engine-strict: 'false'
- node: '16'
engine-strict: 'false'
- node: '18'
engine-strict: 'true'
- node: '20'
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -32,9 +29,6 @@ jobs:
node-version: ${{ matrix.node }}
- name: Install dependencies
env:
CYPRESS_INSTALL_BINARY: 0
NPM_CONFIG_ENGINE_STRICT: ${{ matrix.engine-strict }}
run: |
cd badge-maker
npm install

View File

@@ -13,12 +13,12 @@ jobs:
strategy:
matrix:
include:
- node: '14'
engine-strict: 'false'
- node: '16'
engine-strict: 'true'
- node: '18'
engine-strict: 'false'
- node: '20'
engine-strict: 'false'
steps:
- name: Checkout
uses: actions/checkout@v3

View File

@@ -1,10 +1,13 @@
name: Services@node 17
name: Services@node 18
on:
pull_request:
types: [opened, edited, reopened, synchronize]
push:
branches:
- 'gh-readonly-queue/**'
jobs:
test-services-17:
test-services-18:
runs-on: ubuntu-latest
steps:
@@ -14,7 +17,7 @@ jobs:
- name: Setup
uses: ./.github/actions/setup
with:
node-version: 17
node-version: 18
env:
NPM_CONFIG_ENGINE_STRICT: 'false'

View File

@@ -2,6 +2,9 @@ name: Services
on:
pull_request:
types: [opened, edited, reopened, synchronize]
push:
branches:
- 'gh-readonly-queue/**'
jobs:
test-services:

View File

@@ -4,6 +4,65 @@ Note: this changelog is for the shields.io server. The changelog for the badge-m
---
## server-2023-08-01
- fixup
- fix 'draft release' action part 2
- fix 'draft release' action [#9432](https://github.com/badges/shields/issues/9432)
- Convert `examples` arrays to `openApi` objects (part 1) [#9320](https://github.com/badges/shields/issues/9320)
- add a blog post about GH Tag/Release filter param [#9424](https://github.com/badges/shields/issues/9424)
- add some tests for [docsrs] [#9423](https://github.com/badges/shields/issues/9423)
- Migrate from docs.rs' builds API to status API [#9422](https://github.com/badges/shields/issues/9422)
- exclude assets dir from raster redirects [#9409](https://github.com/badges/shields/issues/9409)
- move some docs to the website [#9347](https://github.com/badges/shields/issues/9347)
- [OpenVSX] Fix OpenVSX API call for unversioned package URLs [#9408](https://github.com/badges/shields/issues/9408)
- devops: automate bug report tests [#9386](https://github.com/badges/shields/issues/9386)
- Add support for [Lemmy] [#9368](https://github.com/badges/shields/issues/9368)
- upgrade to npm 9 [#9323](https://github.com/badges/shields/issues/9323)
- run service/docker builds on merge queue builds [#8943](https://github.com/badges/shields/issues/8943)
- Go back to default YouTube cache [#9372](https://github.com/badges/shields/issues/9372)
- cache docker badges for longer (take 3) [#9369](https://github.com/badges/shields/issues/9369)
- edit comment about styles to remove in future [#9363](https://github.com/badges/shields/issues/9363)
- Revert "[OpenCollective] update opencollective to api v2 (#9346)" [#9362](https://github.com/badges/shields/issues/9362)
- improve docs for github issues search badge [#9360](https://github.com/badges/shields/issues/9360)
- [OpenCollective] update opencollective to api v2 [#9346](https://github.com/badges/shields/issues/9346)
- Add [GitHubDiscussionsSearch] and GitHubRepoDiscussionsSearch service [#9340](https://github.com/badges/shields/issues/9340)
- Allow user to filter github tags and releases [#9193](https://github.com/badges/shields/issues/9193)
- don't URL encode slash in [githubactionsworkflow] badge [#9322](https://github.com/badges/shields/issues/9322)
- add a bit of border to select boxes [#9348](https://github.com/badges/shields/issues/9348)
- deprecate [snyk] badges [#9349](https://github.com/badges/shields/issues/9349)
- increase max-age on [docker] badges, again [#9350](https://github.com/badges/shields/issues/9350)
- Dependency updates
## server-2023-07-02
By far the most significant change in this release is the long-awaited launch of the re-designed frontend:
- migrate frontend to docusaurus [#9014](https://github.com/badges/shields/issues/9014)
- fix a load of spacing issues in frontend content [#9281](https://github.com/badges/shields/issues/9281)
- set a sensible meta description [#9283](https://github.com/badges/shields/issues/9283)
- chore(frontend): open homepage feature links in new tab [#9300](https://github.com/badges/shields/issues/9300)
- adapt opencollective images to theme background [#9298](https://github.com/badges/shields/issues/9298)
- temp fix: wrap code examples tabs in narrow browser windows [#9302](https://github.com/badges/shields/issues/9302)
- add a bit of border to text boxes [#9324](https://github.com/badges/shields/issues/9324)
Other changes in this release:
- cache [dockerpulls] badges for an hour [#9343](https://github.com/badges/shields/issues/9343)
- Mention YouTube API services and link to Google Privacy Policy [#9339](https://github.com/badges/shields/issues/9339)
- allow negative timestamps in relative [date] badge [#9321](https://github.com/badges/shields/issues/9321)
- upgrade to graphql 16 [#9290](https://github.com/badges/shields/issues/9290)
- remove obsolete travis .org examples [#9284](https://github.com/badges/shields/issues/9284)
- increase max age on reddit badges [#9282](https://github.com/badges/shields/issues/9282)
- feat: Add author filter option for [GithubCommitActivity] [#9251](https://github.com/badges/shields/issues/9251)
- Fix: [GithubCommitActivity] invalid branch error handling [#9258](https://github.com/badges/shields/issues/9258)
- Implement a pattern for dealing with upstream APIs which are slow on the first hit; affects [endpoint] [#9233](https://github.com/badges/shields/issues/9233)
- Delete old deprecated services [#9254](https://github.com/badges/shields/issues/9254)
- feat: add 'canceled' status to netlify deploy badge [#9240](https://github.com/badges/shields/issues/9240)
- increase default cache on youtube badges [#9238](https://github.com/badges/shields/issues/9238)
- embiggen youtube cache, again [#9250](https://github.com/badges/shields/issues/9250)
- Dependency updates
## server-2023-06-01
- feat: Add total commits to [GitHubCommitActivity] [#9196](https://github.com/badges/shields/issues/9196)

View File

@@ -9,7 +9,7 @@ COPY package.json package-lock.json /usr/src/app/
COPY badge-maker /usr/src/app/badge-maker/
RUN apk add python3 make g++
RUN npm install -g "npm@>=8"
RUN npm install -g "npm@^9.0.0"
# We need dev deps to build the front end. We don't need Cypress, though.
RUN NODE_ENV=development CYPRESS_INSTALL_BINARY=0 npm ci

View File

@@ -70,7 +70,7 @@ This repo hosts:
[Make your own badges!][custom badges]
(Quick example: `https://img.shields.io/badge/left-right-f39f37`)
[custom badges]: https://shields.io/#your-badge
[custom badges]: http://localhost:3000/badges/static-badge
### Quickstart

View File

@@ -2,7 +2,7 @@
## 4.0.0 [WIP]
- Drop compatibility with Node < 14
- Drop compatibility with Node < 16
## 3.3.1
@@ -275,7 +275,7 @@ badge.loadFont('/path/to/Verdana.ttf', err => {
{ text: ['build', 'passed'], colorscheme: 'green', template: 'flat' },
(svg, err) => {
// svg is a string containing your badge
}
},
)
})
```

View File

@@ -7,19 +7,19 @@ expectError(
makeBadge({
message: 'passed',
style: 'invalid style',
})
}),
)
expectType<string>(
makeBadge({
message: 'passed',
})
}),
)
expectType<string>(
makeBadge({
label: 'build',
message: 'passed',
})
}),
)
expectType<string>(
makeBadge({
@@ -28,7 +28,7 @@ expectType<string>(
labelColor: 'green',
color: 'red',
style: 'flat',
})
}),
)
const error = new ValidationError()

View File

@@ -69,7 +69,7 @@ function getLogoElement({ logo, horizPadding, badgeHeight, logoWidth }) {
function renderBadge(
{ links, leftWidth, rightWidth, height, accessibleText },
content
content,
) {
const width = leftWidth + rightWidth
const leftLink = links[0]
@@ -397,7 +397,7 @@ class Plastic extends Badge {
accessibleText: this.accessibleText,
height: this.constructor.height,
},
[gradient, clipPath, backgroundGroup, this.foregroundGroupElement]
[gradient, clipPath, backgroundGroup, this.foregroundGroupElement],
)
}
}
@@ -446,7 +446,7 @@ class Flat extends Badge {
accessibleText: this.accessibleText,
height: this.constructor.height,
},
[gradient, clipPath, backgroundGroup, this.foregroundGroupElement]
[gradient, clipPath, backgroundGroup, this.foregroundGroupElement],
)
}
}
@@ -478,7 +478,7 @@ class FlatSquare extends Badge {
accessibleText: this.accessibleText,
height: this.constructor.height,
},
[backgroundGroup, this.foregroundGroupElement]
[backgroundGroup, this.foregroundGroupElement],
)
}
}
@@ -748,7 +748,7 @@ function social({
accessibleText,
height: externalHeight,
},
[style, gradients, backgroundGroup, logoElement, foregroundGroup]
[style, gradients, backgroundGroup, logoElement, foregroundGroup],
)
}
@@ -978,7 +978,7 @@ function forTheBadge({
accessibleText: createAccessibleText({ label, message }),
height: BADGE_HEIGHT,
},
[backgroundGroup, foregroundGroup]
[backgroundGroup, foregroundGroup],
)
}

View File

@@ -75,7 +75,7 @@ test(toSvgColor, () => {
given('papayawhip').expect('papayawhip')
given('purple').expect('purple')
forCases([given(''), given(undefined), given('not-a-color')]).expect(
undefined
undefined,
)
given('lightgray').expect('#9f9f9f')
given('informational').expect('#007ec6')

View File

@@ -32,7 +32,7 @@ function _validate(format) {
]
if ('style' in format && !styleValues.includes(format.style)) {
throw new ValidationError(
`Field \`style\` must be one of (${styleValues.toString()})`
`Field \`style\` must be one of (${styleValues.toString()})`,
)
}
}
@@ -46,7 +46,7 @@ function _clean(format) {
cleaned[key] = format[key]
} else {
throw new ValidationError(
`Unexpected field '${key}'. Allowed values are (${expectedKeys.toString()})`
`Unexpected field '${key}'. Allowed values are (${expectedKeys.toString()})`,
)
}
})

View File

@@ -10,12 +10,12 @@ describe('makeBadge function', function () {
makeBadge({
label: 'build',
message: 'passed',
})
}),
).to.satisfy(isSvg)
expect(
makeBadge({
message: 'passed',
})
}),
).to.satisfy(isSvg)
expect(
makeBadge({
@@ -23,7 +23,7 @@ describe('makeBadge function', function () {
message: 'passed',
color: 'green',
style: 'flat',
})
}),
).to.satisfy(isSvg)
})
@@ -32,44 +32,44 @@ describe('makeBadge function', function () {
console.log(x)
expect(() => makeBadge(x)).to.throw(
ValidationError,
'makeBadge takes an argument of type object'
'makeBadge takes an argument of type object',
)
})
expect(() => makeBadge({})).to.throw(
ValidationError,
'Field `message` is required'
'Field `message` is required',
)
expect(() => makeBadge({ label: 'build' })).to.throw(
ValidationError,
'Field `message` is required'
'Field `message` is required',
)
expect(() =>
makeBadge({ label: 'build', message: 'passed', labelColor: 7 })
makeBadge({ label: 'build', message: 'passed', labelColor: 7 }),
).to.throw(ValidationError, 'Field `labelColor` must be of type string')
expect(() =>
makeBadge({ label: 'build', message: 'passed', format: 'png' })
makeBadge({ label: 'build', message: 'passed', format: 'png' }),
).to.throw(ValidationError, "Unexpected field 'format'")
expect(() =>
makeBadge({ label: 'build', message: 'passed', template: 'flat' })
makeBadge({ label: 'build', message: 'passed', template: 'flat' }),
).to.throw(ValidationError, "Unexpected field 'template'")
expect(() =>
makeBadge({ label: 'build', message: 'passed', foo: 'bar' })
makeBadge({ label: 'build', message: 'passed', foo: 'bar' }),
).to.throw(ValidationError, "Unexpected field 'foo'")
expect(() =>
makeBadge({
label: 'build',
message: 'passed',
style: 'something else',
})
}),
).to.throw(
ValidationError,
'Field `style` must be one of (plastic,flat,flat-square,for-the-badge,social)'
'Field `style` must be one of (plastic,flat,flat-square,for-the-badge,social)',
)
expect(() =>
makeBadge({ label: 'build', message: 'passed', style: 'popout' })
makeBadge({ label: 'build', message: 'passed', style: 'popout' }),
).to.throw(
ValidationError,
'Field `style` must be one of (plastic,flat,flat-square,for-the-badge,social)'
'Field `style` must be one of (plastic,flat,flat-square,for-the-badge,social)',
)
})
})

View File

@@ -58,6 +58,6 @@ module.exports = function makeBadge({
logoPadding: logo && label.length ? 3 : 0,
color: toSvgColor(color),
labelColor: toSvgColor(labelColor),
})
}),
)
}

View File

@@ -6,8 +6,8 @@ const snapshot = require('snap-shot-it')
const prettier = require('prettier')
const makeBadge = require('./make-badge')
function expectBadgeToMatchSnapshot(format) {
snapshot(prettier.format(makeBadge(format), { parser: 'html' }))
async function expectBadgeToMatchSnapshot(format) {
snapshot(await prettier.format(makeBadge(format), { parser: 'html' }))
}
function testColor(color = '', colorAttr = 'color') {
@@ -17,7 +17,7 @@ function testColor(color = '', colorAttr = 'color') {
message: 'Bob',
[colorAttr]: color,
format: 'json',
})
}),
).color
}
@@ -67,7 +67,7 @@ describe('The badge generator', function () {
given('bluish'),
given('almostred'),
given('brightmaroon'),
given('cactus')
given('cactus'),
).expect(undefined)
})
})
@@ -87,8 +87,8 @@ describe('The badge generator', function () {
.and.to.include('grown')
})
it('should match snapshot', function () {
expectBadgeToMatchSnapshot({
it('should match snapshot', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -138,14 +138,14 @@ describe('The badge generator', function () {
message: 'Bob',
format: 'svg',
style: 'unknown_style',
})
}),
).to.throw(Error, "Unknown badge style: 'unknown_style'")
})
})
describe('"flat" template badge generation', function () {
it('should match snapshots: message/label, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -155,8 +155,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -167,8 +167,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -177,8 +177,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -188,8 +188,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo and labelColor', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo and labelColor', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -200,8 +200,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with links', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with links', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -212,8 +212,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: black text when the label color is light', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: black text when the label color is light', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -223,8 +223,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: black text when the message color is light', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: black text when the message color is light', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -236,8 +236,8 @@ describe('The badge generator', function () {
})
describe('"flat-square" template badge generation', function () {
it('should match snapshots: message/label, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -247,8 +247,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -259,8 +259,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -269,8 +269,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -280,8 +280,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo and labelColor', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo and labelColor', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -292,8 +292,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with links', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with links', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -304,8 +304,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: black text when the label color is light', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: black text when the label color is light', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -315,8 +315,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: black text when the message color is light', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: black text when the message color is light', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -328,8 +328,8 @@ describe('The badge generator', function () {
})
describe('"plastic" template badge generation', function () {
it('should match snapshots: message/label, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -339,8 +339,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -351,8 +351,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -361,8 +361,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -372,8 +372,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo and labelColor', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo and labelColor', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -384,8 +384,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with links', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with links', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -396,8 +396,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: black text when the label color is light', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: black text when the label color is light', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -407,8 +407,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: black text when the message color is light', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: black text when the message color is light', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -428,7 +428,7 @@ describe('The badge generator', function () {
message: 1999,
format: 'svg',
style: 'for-the-badge',
})
}),
)
.to.include('1998')
.and.to.include('1999')
@@ -441,14 +441,14 @@ describe('The badge generator', function () {
message: '1 string',
format: 'svg',
style: 'for-the-badge',
})
}),
)
.to.include('LABEL')
.and.to.include('1 STRING')
})
it('should match snapshots: message/label, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -458,8 +458,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -470,8 +470,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -480,8 +480,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -491,8 +491,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo and labelColor', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo and labelColor', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -503,8 +503,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with links', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with links', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -515,8 +515,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: black text when the label color is light', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: black text when the label color is light', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -526,8 +526,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: black text when the message color is light', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: black text when the message color is light', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -546,7 +546,7 @@ describe('The badge generator', function () {
message: 'some-value',
format: 'svg',
style: 'social',
})
}),
)
.to.include('Some-key')
.and.to.include('some-value')
@@ -560,14 +560,14 @@ describe('The badge generator', function () {
message: 'some-value',
format: 'json',
style: 'social',
})
}),
)
.to.include('""')
.and.to.include('some-value')
})
it('should match snapshots: message/label, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -577,8 +577,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -589,8 +589,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, no logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, no logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -599,8 +599,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -610,8 +610,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message only, with logo and labelColor', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message only, with logo and labelColor', async function () {
await expectBadgeToMatchSnapshot({
label: '',
message: 'grown',
format: 'svg',
@@ -622,8 +622,8 @@ describe('The badge generator', function () {
})
})
it('should match snapshots: message/label, with links', function () {
expectBadgeToMatchSnapshot({
it('should match snapshots: message/label, with links', async function () {
await expectBadgeToMatchSnapshot({
label: 'cactus',
message: 'grown',
format: 'svg',
@@ -636,8 +636,8 @@ describe('The badge generator', function () {
})
describe('badges with logos should always produce the same badge', function () {
it('badge with logo', function () {
expectBadgeToMatchSnapshot({
it('badge with logo', async function () {
await expectBadgeToMatchSnapshot({
label: 'label',
message: 'message',
format: 'svg',

View File

@@ -66,7 +66,7 @@ class XmlElement {
})
.join(' ')
return stripXmlWhitespace(
`<${this.name}${attrsStr}>${content}</${this.name}>`
`<${this.name}${attrsStr}>${content}</${this.name}>`,
)
}
return stripXmlWhitespace(`<${this.name}${attrsStr}/>`)
@@ -88,7 +88,7 @@ class ElementList {
typeof el.render === 'function'
? acc + el.render()
: acc + escapeXml(el),
''
'',
)
}
}

View File

@@ -26,8 +26,7 @@
"badge": "lib/badge-cli.js"
},
"engines": {
"node": ">= 14",
"npm": ">= 6"
"node": ">=16"
},
"collective": {
"type": "opencollective",

View File

@@ -7,7 +7,7 @@ describe('Badge URL helper functions', function () {
given('single trailing underscore_').expect('single trailing underscore ')
given('__double leading underscores').expect('_double leading underscores')
given('double trailing underscores__').expect(
'double trailing underscores_'
'double trailing underscores_',
)
given('treble___underscores').expect('treble_ underscores')
given('fourfold____underscores').expect('fourfold__underscores')

View File

@@ -11,7 +11,7 @@ class AuthHelper {
isRequired = false,
defaultToEmptyStringForUser = false,
},
config
config,
) {
if (!userKey && !passKey) {
throw Error('Expected userKey or passKey to be set')
@@ -142,7 +142,7 @@ class AuthHelper {
withBasicAuth(requestParams) {
return this._withAnyAuth(requestParams, requestParams =>
this.constructor._mergeAuth(requestParams, this._basicAuth)
this.constructor._mergeAuth(requestParams, this._basicAuth),
)
}
@@ -172,13 +172,13 @@ class AuthHelper {
withBearerAuthHeader(
requestParams,
bearerKey = 'Bearer' // lgtm [js/hardcoded-credentials]
bearerKey = 'Bearer', // lgtm [js/hardcoded-credentials]
) {
return this._withAnyAuth(requestParams, requestParams =>
this.constructor._mergeHeaders(
requestParams,
this._bearerAuthHeader(bearerKey)
)
this._bearerAuthHeader(bearerKey),
),
)
}
@@ -204,7 +204,7 @@ class AuthHelper {
this.constructor._mergeQueryParams(requestParams, {
...(userKey ? { [userKey]: this._user } : undefined),
...(passKey ? { [passKey]: this._pass } : undefined),
})
}),
)
}
}

View File

@@ -8,12 +8,13 @@ describe('AuthHelper', function () {
it('throws without userKey or passKey', function () {
expect(() => new AuthHelper({}, {})).to.throw(
Error,
'Expected userKey or passKey to be set'
'Expected userKey or passKey to be set',
)
})
it('throws without serviceKey or authorizedOrigins', function () {
expect(
() => new AuthHelper({ userKey: 'myci_user', passKey: 'myci_pass' }, {})
() =>
new AuthHelper({ userKey: 'myci_user', passKey: 'myci_pass' }, {}),
).to.throw(Error, 'Expected authorizedOrigins or serviceKey to be set')
})
it('throws when authorizedOrigins is not an array', function () {
@@ -25,8 +26,8 @@ describe('AuthHelper', function () {
passKey: 'myci_pass',
authorizedOrigins: true,
},
{ private: {} }
)
{ private: {} },
),
).to.throw(Error, 'Expected authorizedOrigins to be an array of origins')
})
})
@@ -35,7 +36,7 @@ describe('AuthHelper', function () {
function validate(config, privateConfig) {
return new AuthHelper(
{ authorizedOrigins: ['https://example.test'], ...config },
{ private: privateConfig }
{ private: privateConfig },
).isValid
}
test(validate, () => {
@@ -43,20 +44,20 @@ describe('AuthHelper', function () {
// Fully configured user + pass.
given(
{ userKey: 'myci_user', passKey: 'myci_pass', isRequired: true },
{ myci_user: 'admin', myci_pass: 'abc123' }
{ myci_user: 'admin', myci_pass: 'abc123' },
),
given(
{ userKey: 'myci_user', passKey: 'myci_pass' },
{ myci_user: 'admin', myci_pass: 'abc123' }
{ myci_user: 'admin', myci_pass: 'abc123' },
),
// Fully configured user or pass.
given(
{ userKey: 'myci_user', isRequired: true },
{ myci_user: 'admin' }
{ myci_user: 'admin' },
),
given(
{ passKey: 'myci_pass', isRequired: true },
{ myci_pass: 'abc123' }
{ myci_pass: 'abc123' },
),
given({ userKey: 'myci_user' }, { myci_user: 'admin' }),
given({ passKey: 'myci_pass' }, { myci_pass: 'abc123' }),
@@ -70,16 +71,16 @@ describe('AuthHelper', function () {
// Partly configured.
given(
{ userKey: 'myci_user', passKey: 'myci_pass', isRequired: true },
{ myci_user: 'admin' }
{ myci_user: 'admin' },
),
given(
{ userKey: 'myci_user', passKey: 'myci_pass' },
{ myci_user: 'admin' }
{ myci_user: 'admin' },
),
// Missing required config.
given(
{ userKey: 'myci_user', passKey: 'myci_pass', isRequired: true },
{}
{},
),
given({ userKey: 'myci_user', isRequired: true }, {}),
given({ passKey: 'myci_pass', isRequired: true }, {}),
@@ -91,18 +92,18 @@ describe('AuthHelper', function () {
function validate(config, privateConfig) {
return new AuthHelper(
{ authorizedOrigins: ['https://example.test'], ...config },
{ private: privateConfig }
{ private: privateConfig },
)._basicAuth
}
test(validate, () => {
forCases([
given(
{ userKey: 'myci_user', passKey: 'myci_pass', isRequired: true },
{ myci_user: 'admin', myci_pass: 'abc123' }
{ myci_user: 'admin', myci_pass: 'abc123' },
),
given(
{ userKey: 'myci_user', passKey: 'myci_pass' },
{ myci_user: 'admin', myci_pass: 'abc123' }
{ myci_user: 'admin', myci_pass: 'abc123' },
),
]).expect({ username: 'admin', password: 'abc123' })
given({ userKey: 'myci_user' }, { myci_user: 'admin' }).expect({
@@ -114,11 +115,11 @@ describe('AuthHelper', function () {
password: 'abc123',
})
given({ userKey: 'myci_user', passKey: 'myci_pass' }, {}).expect(
undefined
undefined,
)
given(
{ passKey: 'myci_pass', defaultToEmptyStringForUser: true },
{ myci_pass: 'abc123' }
{ myci_pass: 'abc123' },
).expect({
username: '',
password: 'abc123',
@@ -168,7 +169,7 @@ describe('AuthHelper', function () {
expect(() =>
authHelper.enforceStrictSsl({
options: { https: { rejectUnauthorized: false } },
})
}),
).to.throw(InvalidParameter)
})
})
@@ -192,7 +193,7 @@ describe('AuthHelper', function () {
expect(() =>
authHelper.enforceStrictSsl({
options: { https: { rejectUnauthorized: false } },
})
}),
).not.to.throw()
})
})
@@ -318,7 +319,7 @@ describe('AuthHelper', function () {
},
},
private: { myci_user: 'admin', myci_pass: 'abc123' },
}
},
)
const withBasicAuth = requestOptions =>
authHelper.withBasicAuth(requestOptions)
@@ -376,7 +377,7 @@ describe('AuthHelper', function () {
withBasicAuth({
url: 'https://myci.test/api',
options: { https: { rejectUnauthorized: false } },
})
}),
).to.throw(InvalidParameter)
})
})

View File

@@ -91,7 +91,7 @@ class BaseGraphqlService extends BaseService {
throw exception
} else {
throw Error(
`transformErrors() must return a ShieldsRuntimeError; got ${exception}`
`transformErrors() must return a ShieldsRuntimeError; got ${exception}`,
)
}
}

View File

@@ -35,23 +35,23 @@ describe('BaseGraphqlService', function () {
Promise.resolve({
buffer: '{"some": "json"}',
res: { statusCode: 200 },
})
}),
)
})
it('invokes _requestFetcher', async function () {
await DummyGraphqlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
'http://example.com/graphql',
{
body: '{"query":"{\\n requiredString\\n}\\n","variables":{}}',
body: '{"query":"{\\n requiredString\\n}","variables":{}}',
headers: { Accept: 'application/json' },
method: 'POST',
}
},
)
})
@@ -74,17 +74,17 @@ describe('BaseGraphqlService', function () {
await WithOptions.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
'http://example.com/graphql',
{
body: '{"query":"{\\n requiredString\\n}\\n","variables":{}}',
body: '{"query":"{\\n requiredString\\n}","variables":{}}',
headers: { Accept: 'application/json' },
method: 'POST',
searchParams: { queryParam: 123 },
}
},
)
})
})
@@ -98,8 +98,8 @@ describe('BaseGraphqlService', function () {
expect(
await DummyGraphqlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
message: 'some-string',
})
@@ -113,8 +113,8 @@ describe('BaseGraphqlService', function () {
expect(
await DummyGraphqlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -130,8 +130,8 @@ describe('BaseGraphqlService', function () {
expect(
await DummyGraphqlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -149,8 +149,8 @@ describe('BaseGraphqlService', function () {
expect(
await DummyGraphqlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -188,8 +188,8 @@ describe('BaseGraphqlService', function () {
expect(
await WithErrorHandler.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',

View File

@@ -28,21 +28,21 @@ describe('BaseJsonService', function () {
Promise.resolve({
buffer: '{"some": "json"}',
res: { statusCode: 200 },
})
}),
)
})
it('invokes _requestFetcher', async function () {
await DummyJsonService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
'http://example.com/foo.json',
{
headers: { Accept: 'application/json' },
}
},
)
})
@@ -60,7 +60,7 @@ describe('BaseJsonService', function () {
await WithOptions.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
@@ -69,7 +69,7 @@ describe('BaseJsonService', function () {
headers: { Accept: 'application/json' },
method: 'POST',
searchParams: { queryParam: 123 },
}
},
)
})
})
@@ -83,8 +83,8 @@ describe('BaseJsonService', function () {
expect(
await DummyJsonService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
message: 'some-string',
})
@@ -98,8 +98,8 @@ describe('BaseJsonService', function () {
expect(
await DummyJsonService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -115,8 +115,8 @@ describe('BaseJsonService', function () {
expect(
await DummyJsonService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',

View File

@@ -33,14 +33,14 @@ export default class BaseStaticService extends BaseService {
{},
serviceConfig,
namedParams,
queryParams
queryParams,
)
const badgeData = coalesceBadge(
queryParams,
serviceData,
this.defaultBadgeData,
this
this,
)
// The final capture group is the extension.

View File

@@ -28,7 +28,7 @@ describe('BaseSvgScrapingService', function () {
describe('valueFromSvgBadge', function () {
it('should find the correct value', function () {
expect(BaseSvgScrapingService.valueFromSvgBadge(exampleSvg)).to.equal(
exampleMessage
exampleMessage,
)
})
})
@@ -40,21 +40,21 @@ describe('BaseSvgScrapingService', function () {
Promise.resolve({
buffer: exampleSvg,
res: { statusCode: 200 },
})
}),
)
})
it('invokes _requestFetcher with the expected header', async function () {
await DummySvgScrapingService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
'http://example.com/foo.svg',
{
headers: { Accept: 'image/svg+xml' },
}
},
)
})
@@ -75,7 +75,7 @@ describe('BaseSvgScrapingService', function () {
await WithCustomOptions.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
@@ -84,7 +84,7 @@ describe('BaseSvgScrapingService', function () {
method: 'POST',
headers: { Accept: 'image/svg+xml' },
searchParams: { queryParam: 123 },
}
},
)
})
})
@@ -98,8 +98,8 @@ describe('BaseSvgScrapingService', function () {
expect(
await DummySvgScrapingService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
message: exampleMessage,
})
@@ -124,8 +124,8 @@ describe('BaseSvgScrapingService', function () {
expect(
await WithValueMatcher.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
message: 'a different message',
})
@@ -139,8 +139,8 @@ describe('BaseSvgScrapingService', function () {
expect(
await DummySvgScrapingService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',

View File

@@ -28,21 +28,21 @@ describe('BaseXmlService', function () {
Promise.resolve({
buffer: '<requiredString>some-string</requiredString>',
res: { statusCode: 200 },
})
}),
)
})
it('invokes _requestFetcher', async function () {
await DummyXmlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
'http://example.com/foo.xml',
{
headers: { Accept: 'application/xml, text/xml' },
}
},
)
})
@@ -62,7 +62,7 @@ describe('BaseXmlService', function () {
await WithCustomOptions.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
@@ -71,7 +71,7 @@ describe('BaseXmlService', function () {
headers: { Accept: 'application/xml, text/xml' },
method: 'POST',
searchParams: { queryParam: 123 },
}
},
)
})
})
@@ -85,8 +85,8 @@ describe('BaseXmlService', function () {
expect(
await DummyXmlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
message: 'some-string',
})
@@ -112,8 +112,8 @@ describe('BaseXmlService', function () {
expect(
await DummyXmlServiceWithParserOption.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
message: 'some-string with trailing whitespace ',
})
@@ -127,8 +127,8 @@ describe('BaseXmlService', function () {
expect(
await DummyXmlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -144,8 +144,8 @@ describe('BaseXmlService', function () {
expect(
await DummyXmlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',

View File

@@ -44,14 +44,14 @@ describe('BaseYamlService', function () {
Promise.resolve({
buffer: expectedYaml,
res: { statusCode: 200 },
})
}),
)
})
it('invokes _requestFetcher', async function () {
await DummyYamlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
@@ -61,7 +61,7 @@ describe('BaseYamlService', function () {
Accept:
'text/x-yaml, text/yaml, application/x-yaml, application/yaml, text/plain',
},
}
},
)
})
@@ -79,7 +79,7 @@ describe('BaseYamlService', function () {
await WithOptions.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
{ handleInternalErrors: false },
)
expect(requestFetcher).to.have.been.calledOnceWith(
@@ -91,7 +91,7 @@ describe('BaseYamlService', function () {
},
method: 'POST',
searchParams: { queryParam: 123 },
}
},
)
})
})
@@ -105,8 +105,8 @@ describe('BaseYamlService', function () {
expect(
await DummyYamlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
message: 'some-string',
})
@@ -120,8 +120,8 @@ describe('BaseYamlService', function () {
expect(
await DummyYamlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -137,8 +137,8 @@ describe('BaseYamlService', function () {
expect(
await DummyYamlService.invoke(
{ requestFetcher },
{ handleInternalErrors: false }
)
{ handleInternalErrors: false },
),
).to.deep.equal({
isError: true,
color: 'lightgray',

View File

@@ -44,7 +44,7 @@ const optionalStringWhenNamedLogoPresent = Joi.alternatives().conditional(
{
is: Joi.string().required(),
then: Joi.string(),
}
},
)
const optionalNumberWhenAnyLogoPresent = Joi.alternatives()
@@ -183,12 +183,28 @@ class BaseService {
Joi.assert(
this.defaultBadgeData,
defaultBadgeDataSchema,
`Default badge data for ${this.name}`
`Default badge data for ${this.name}`,
)
this.examples.forEach((example, index) =>
validateExample(example, index, this)
validateExample(example, index, this),
)
// ensure openApi spec matches route
if (this.openApi) {
const preparedRoute = prepareRoute(this.route)
for (const [key, value] of Object.entries(this.openApi)) {
let example = key
for (const param of value.get.parameters) {
example = example.replace(`{${param.name}}`, param.example)
}
if (!example.match(preparedRoute.regex)) {
throw new Error(
`Inconsistent Open Api spec and Route found for service ${this.name}`,
)
}
}
}
}
static getDefinition() {
@@ -197,7 +213,7 @@ class BaseService {
const queryParams = getQueryParamNames(this.route)
const examples = this.examples.map((example, index) =>
transformExample(example, index, this)
transformExample(example, index, this),
)
let route
@@ -218,7 +234,7 @@ class BaseService {
constructor(
{ requestFetcher, authHelper, metricHelper },
{ handleInternalErrors }
{ handleInternalErrors },
) {
this._requestFetcher = requestFetcher
this.authHelper = authHelper
@@ -234,9 +250,9 @@ class BaseService {
const params = new URLSearchParams(
Object.fromEntries(
Object.entries(options.searchParams).filter(
([k, v]) => v !== undefined
)
)
([k, v]) => v !== undefined,
),
),
)
logUrl = `${url}?${params.toString()}`
delete logOptions.searchParams
@@ -244,12 +260,12 @@ class BaseService {
logTrace(
emojic.bowAndArrow,
'Request',
`${logUrl}\n${JSON.stringify(logOptions, null, 2)}`
`${logUrl}\n${JSON.stringify(logOptions, null, 2)}`,
)
const { res, buffer } = await this._requestFetcher(
url,
options,
systemErrors
systemErrors,
)
await this._meterResponse(res, buffer)
logTrace(emojic.dart, 'Response status code', res.statusCode)
@@ -279,7 +295,7 @@ class BaseService {
prettyErrorMessage = 'invalid response data',
includeKeys = false,
allowAndStripUnknownKeys = true,
} = {}
} = {},
) {
return validate(
{
@@ -291,7 +307,7 @@ class BaseService {
allowAndStripUnknownKeys,
},
data,
schema
schema,
)
}
@@ -347,7 +363,7 @@ class BaseService {
'unhandledError',
emojic.boom,
'Unhandled internal error',
error
error,
)
) {
// This is where we end up if an unhandled exception is thrown in
@@ -365,7 +381,7 @@ class BaseService {
'unhandledError',
emojic.boom,
'Unhandled internal error',
error
error,
)
throw error
}
@@ -375,7 +391,7 @@ class BaseService {
context = {},
config = {},
namedParams = {},
queryParams = {}
queryParams = {},
) {
trace.logTrace('inbound', emojic.womanCook, 'Service class', this.name)
trace.logTrace('inbound', emojic.ticket, 'Named params', namedParams)
@@ -409,13 +425,13 @@ class BaseService {
traceSuccessMessage: 'Query params after validation',
},
queryParams,
queryParamSchema
queryParamSchema,
)
trace.logTrace(
'inbound',
emojic.crayon,
'Query params after validation',
queryParams
queryParams,
)
} catch (error) {
serviceError = error
@@ -429,7 +445,7 @@ class BaseService {
try {
serviceData = await serviceInstance.handle(
namedParams,
transformedQueryParams
transformedQueryParams,
)
serviceInstance._validateServiceData(serviceData)
} catch (error) {
@@ -454,7 +470,7 @@ class BaseService {
librariesIoApiProvider,
metricInstance,
},
serviceConfig
serviceConfig,
) {
const { cacheHeaders: cacheHeaderConfig } = serviceConfig
const { regex, captureNames } = prepareRoute(this.route)
@@ -482,14 +498,14 @@ class BaseService {
},
serviceConfig,
namedParams,
queryParams
queryParams,
)
const badgeData = coalesceBadge(
queryParams,
serviceData,
this.defaultBadgeData,
this
this,
)
// The final capture group is the extension.
const format = (match.slice(-1)[0] || '.svg').replace(/^\./, '')
@@ -498,7 +514,7 @@ class BaseService {
metricHandle.noteResponseSent()
},
cacheLength: this._cacheLength,
})
}),
)
}
}

View File

@@ -72,8 +72,8 @@ describe('BaseService', function () {
{},
defaultConfig,
{ namedParamA: 'bar.bar.bar' },
{ queryParamA: '!' }
)
{ queryParamA: '!' },
),
).to.deep.equal({
message: 'Hello namedParamA: bar.bar.bar with queryParamA: !',
})
@@ -85,8 +85,8 @@ describe('BaseService', function () {
{},
defaultConfig,
{ namedParamA: 'bar.bar.bar' },
{ queryParamA: ['foo', 'bar'] }
)
{ queryParamA: ['foo', 'bar'] },
),
).to.deep.equal({
color: 'red',
isError: true,
@@ -97,13 +97,13 @@ describe('BaseService', function () {
describe('Required overrides', function () {
it('Should throw if render() is not overridden', function () {
expect(() => BaseService.render()).to.throw(
/^render\(\) function not implemented for BaseService$/
/^render\(\) function not implemented for BaseService$/,
)
})
it('Should throw if route is not overridden', function () {
return expect(BaseService.invoke({}, {}, {})).to.be.rejectedWith(
/^Route not defined for BaseService$/
/^Route not defined for BaseService$/,
)
})
@@ -112,13 +112,13 @@ describe('BaseService', function () {
}
it('Should throw if handle() is not overridden', function () {
return expect(WithRoute.invoke({}, {}, {})).to.be.rejectedWith(
/^Handler not implemented for WithRoute$/
/^Handler not implemented for WithRoute$/,
)
})
it('Should throw if category is not overridden', function () {
expect(() => BaseService.category).to.throw(
/^Category not set for BaseService$/
/^Category not set for BaseService$/,
)
})
})
@@ -135,25 +135,25 @@ describe('BaseService', function () {
{},
defaultConfig,
{ namedParamA: 'bar.bar.bar' },
{ queryParamA: '!' }
{ queryParamA: '!' },
)
expect(trace.logTrace).to.be.calledWithMatch(
'inbound',
sinon.match.string,
'Service class',
'DummyService'
'DummyService',
)
expect(trace.logTrace).to.be.calledWith(
'inbound',
sinon.match.string,
'Named params',
{ namedParamA: 'bar.bar.bar' }
{ namedParamA: 'bar.bar.bar' },
)
expect(trace.logTrace).to.be.calledWith(
'inbound',
sinon.match.string,
'Query params after validation',
{ queryParamA: '!' }
{ queryParamA: '!' },
)
})
})
@@ -171,7 +171,7 @@ describe('BaseService', function () {
const serviceData = await LinkService.invoke(
{},
{ handleInternalErrors: false },
{ namedParamA: 'bar.bar.bar' }
{ namedParamA: 'bar.bar.bar' },
)
expect(serviceData).to.deep.equal({
@@ -194,7 +194,7 @@ describe('BaseService', function () {
await ThrowingService.invoke(
{},
{ handleInternalErrors: false },
{ namedParamA: 'bar.bar.bar' }
{ namedParamA: 'bar.bar.bar' },
)
expect.fail('Expected to throw')
} catch (e) {
@@ -212,7 +212,7 @@ describe('BaseService', function () {
await ThrowingService.invoke(
{},
{ handleInternalErrors: false },
{ namedParamA: 'bar.bar.bar' }
{ namedParamA: 'bar.bar.bar' },
)
expect.fail('Expected to throw')
} catch (e) {
@@ -233,8 +233,8 @@ describe('BaseService', function () {
await ThrowingService.invoke(
{},
{ handleInternalErrors: true },
{ namedParamA: 'bar.bar.bar' }
)
{ namedParamA: 'bar.bar.bar' },
),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -251,7 +251,7 @@ describe('BaseService', function () {
}
}
expect(
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' })
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' }),
).to.deep.equal({
isError: true,
color: 'red',
@@ -266,7 +266,7 @@ describe('BaseService', function () {
}
}
expect(
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' })
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' }),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -281,7 +281,7 @@ describe('BaseService', function () {
}
}
expect(
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' })
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' }),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -296,7 +296,7 @@ describe('BaseService', function () {
}
}
expect(
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' })
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' }),
).to.deep.equal({
isError: true,
color: 'lightgray',
@@ -311,7 +311,7 @@ describe('BaseService', function () {
}
}
expect(
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' })
await ThrowingService.invoke({}, {}, { namedParamA: 'bar.bar.bar' }),
).to.deep.equal({
isError: true,
color: 'red',
@@ -336,7 +336,7 @@ describe('BaseService', function () {
mockHandleRequest = sinon.spy()
DummyService.register(
{ camp: mockCamp, handleRequest: mockHandleRequest },
defaultConfig
defaultConfig,
)
})
@@ -413,8 +413,8 @@ describe('BaseService', function () {
expect(() =>
DummyService._validate(
{ requiredString: ['this', "shouldn't", 'work'] },
dummySchema
)
dummySchema,
),
)
.to.throw()
.instanceof(InvalidResponse)
@@ -436,7 +436,7 @@ describe('BaseService', function () {
})
const serviceInstance = new DummyService(
{ requestFetcher },
defaultConfig
defaultConfig,
)
const url = 'some-url'
@@ -453,14 +453,14 @@ describe('BaseService', function () {
`${url}?param1=foobar\n${JSON.stringify(
{ headers: options.headers },
null,
2
)}`
2,
)}`,
)
expect(trace.logTrace).to.be.calledWithMatch(
'fetch',
sinon.match.string,
'Response status code',
200
200,
)
})
@@ -471,7 +471,7 @@ describe('BaseService', function () {
})
const serviceInstance = new DummyService(
{ requestFetcher },
defaultConfig
defaultConfig,
)
try {
@@ -504,17 +504,17 @@ describe('BaseService', function () {
const serviceInstance =
new DummyServiceWithServiceResponseSizeMetricEnabled(
{ requestFetcher, metricHelper },
defaultConfig
defaultConfig,
)
await serviceInstance._request({ url })
expect(await register.getSingleMetricAsString('service_response_bytes'))
.to.contain(
'service_response_bytes_bucket{le="65536",category="other",family="undefined",service="dummy_service_with_service_response_size_metric_enabled"} 0\n'
'service_response_bytes_bucket{le="65536",category="other",family="undefined",service="dummy_service_with_service_response_size_metric_enabled"} 0\n',
)
.and.to.contain(
'service_response_bytes_bucket{le="131072",category="other",family="undefined",service="dummy_service_with_service_response_size_metric_enabled"} 1\n'
'service_response_bytes_bucket{le="131072",category="other",family="undefined",service="dummy_service_with_service_response_size_metric_enabled"} 1\n',
)
})
@@ -529,13 +529,13 @@ describe('BaseService', function () {
})
const serviceInstance = new DummyService(
{ requestFetcher, metricHelper },
defaultConfig
defaultConfig,
)
await serviceInstance._request({ url })
expect(
await register.getSingleMetricAsString('service_response_bytes')
await register.getSingleMetricAsString('service_response_bytes'),
).to.not.contain('service_response_bytes_bucket')
})
})
@@ -565,8 +565,8 @@ describe('BaseService', function () {
},
private: { myci_pass: 'abc123' },
},
{ namedParamA: 'bar.bar.bar' }
)
{ namedParamA: 'bar.bar.bar' },
),
).to.deep.equal({ message: 'The CI password is abc123' })
})
@@ -583,8 +583,8 @@ describe('BaseService', function () {
},
{
namedParamA: 'bar.bar.bar',
}
)
},
),
).to.deep.equal({
color: 'lightgray',
isError: true,

View File

@@ -41,7 +41,7 @@ function coalesceCacheLength({
const cacheLength = coalesce(
serviceOverrideCacheLengthSeconds,
serviceDefaultCacheLengthSeconds,
defaultCacheLengthSeconds
defaultCacheLengthSeconds,
)
// Overrides can apply _more_ caching, but not less. Query param overriding

View File

@@ -125,7 +125,7 @@ describe('Cache header functions', function () {
it('should set the expected Cache-Control header', function () {
expect(res._headers['cache-control']).to.equal(
'no-cache, no-store, must-revalidate'
'no-cache, no-store, must-revalidate',
)
})
@@ -141,7 +141,7 @@ describe('Cache header functions', function () {
it('should set the expected Cache-Control header', function () {
expect(res._headers['cache-control']).to.equal(
'max-age=123, s-maxage=123'
'max-age=123, s-maxage=123',
)
})
@@ -156,7 +156,7 @@ describe('Cache header functions', function () {
it('sets the expected fields', function () {
const expectedFields = ['date', 'cache-control', 'expires']
expectedFields.forEach(field =>
expect(res._headers[field]).to.equal(undefined)
expect(res._headers[field]).to.equal(undefined),
)
setCacheHeaders({
@@ -169,7 +169,7 @@ describe('Cache header functions', function () {
expectedFields.forEach(field =>
expect(res._headers[field])
.to.be.a('string')
.and.have.lengthOf.at.least(1)
.and.have.lengthOf.at.least(1),
)
})
})
@@ -181,7 +181,7 @@ describe('Cache header functions', function () {
it('should set the expected Cache-Control header', function () {
expect(res._headers['cache-control']).to.equal(
`max-age=${24 * 3600}, s-maxage=${24 * 3600}`
`max-age=${24 * 3600}, s-maxage=${24 * 3600}`,
)
})
@@ -190,7 +190,7 @@ describe('Cache header functions', function () {
expect(new Date(lastModified)).to.be.withinTime(
// Within the last 60 seconds.
new Date(Date.now() - 60 * 1000),
new Date()
new Date(),
)
})
})
@@ -221,7 +221,7 @@ describe('Cache header functions', function () {
})
expect(serverHasBeenUpSinceResourceCached(req)).to.equal(false)
})
}
},
)
context(
'when the If-Modified-Since header is after the process started',
@@ -233,7 +233,7 @@ describe('Cache header functions', function () {
})
expect(serverHasBeenUpSinceResourceCached(req)).to.equal(true)
})
}
},
)
})
})

View File

@@ -13,7 +13,7 @@ export default function checkErrorResponse(httpErrors = {}) {
error = new NotFound({ prettyMessage: httpErrors[404] })
} else if (res.statusCode !== 200) {
const underlying = Error(
`Got status code ${res.statusCode} (expected 200)`
`Got status code ${res.statusCode} (expected 200)`,
)
const props = { underlyingError: underlying }
if (httpErrors[res.statusCode] !== undefined) {

View File

@@ -56,7 +56,7 @@ describe('async error handler', function () {
} catch (e) {
expect(e).to.be.an.instanceof(InvalidResponse)
expect(e.message).to.equal(
'Invalid Response: Got status code 429 (expected 200)'
'Invalid Response: Got status code 429 (expected 200)',
)
expect(e.prettyMessage).to.equal('rate limited by upstream service')
expect(e.response).to.equal(res)
@@ -72,10 +72,10 @@ describe('async error handler', function () {
} catch (e) {
expect(e).to.be.an.instanceof(InvalidResponse)
expect(e.message).to.equal(
'Invalid Response: Got status code 429 (expected 200)'
'Invalid Response: Got status code 429 (expected 200)',
)
expect(e.prettyMessage).to.equal(
"terribly sorry but that's one too many requests"
"terribly sorry but that's one too many requests",
)
}
})
@@ -90,7 +90,7 @@ describe('async error handler', function () {
} catch (e) {
expect(e).to.be.an.instanceof(InvalidResponse)
expect(e.message).to.equal(
'Invalid Response: Got status code 499 (expected 200)'
'Invalid Response: Got status code 499 (expected 200)',
)
expect(e.prettyMessage).to.equal('invalid')
expect(e.response).to.equal(res)
@@ -106,7 +106,7 @@ describe('async error handler', function () {
} catch (e) {
expect(e).to.be.an.instanceof(InvalidResponse)
expect(e.message).to.equal(
'Invalid Response: Got status code 403 (expected 200)'
'Invalid Response: Got status code 403 (expected 200)',
)
expect(e.prettyMessage).to.equal('access denied')
}
@@ -122,7 +122,7 @@ describe('async error handler', function () {
} catch (e) {
expect(e).to.be.an.instanceof(Inaccessible)
expect(e.message).to.equal(
'Inaccessible: Got status code 503 (expected 200)'
'Inaccessible: Got status code 503 (expected 200)',
)
expect(e.prettyMessage).to.equal('inaccessible')
expect(e.response).to.equal(res)
@@ -138,7 +138,7 @@ describe('async error handler', function () {
} catch (e) {
expect(e).to.be.an.instanceof(Inaccessible)
expect(e.message).to.equal(
'Inaccessible: Got status code 500 (expected 200)'
'Inaccessible: Got status code 500 (expected 200)',
)
expect(e.prettyMessage).to.equal('server overloaded')
}

View File

@@ -36,7 +36,7 @@ export default function coalesceBadge(
serviceData,
// These two parameters were kept separate to make tests clearer.
defaultBadgeData,
{ category, _cacheLength: defaultCacheSeconds } = {}
{ category, _cacheLength: defaultCacheSeconds } = {},
) {
// The "overrideX" naming is based on services that provide badge
// parameters themselves, which can be overridden by a query string
@@ -141,7 +141,7 @@ export default function coalesceBadge(
} else {
namedLogo = coalesce(
serviceNamedLogo,
style === 'social' ? defaultNamedLogo : undefined
style === 'social' ? defaultNamedLogo : undefined,
)
namedLogoColor = coalesce(overrideLogoColor, serviceLogoColor)
}
@@ -166,13 +166,13 @@ export default function coalesceBadge(
isError ? undefined : overrideColor,
serviceColor,
defaultColor,
'lightgrey'
'lightgrey',
),
labelColor: coalesce(
// In case of an error, disregard user's color override.
isError ? undefined : overrideLabelColor,
serviceLabelColor,
defaultLabelColor
defaultLabelColor,
),
style,
namedLogo,

View File

@@ -25,7 +25,7 @@ describe('coalesceBadge', function () {
it('overrides the label', function () {
expect(
coalesceBadge({ label: 'purr count' }, { label: 'purrs' }, {})
coalesceBadge({ label: 'purr count' }, { label: 'purrs' }, {}),
).to.include({ label: 'purr count' })
})
})
@@ -54,11 +54,11 @@ describe('coalesceBadge', function () {
it('overrides the color', function () {
expect(
coalesceBadge({ color: '10ADED' }, { color: 'red' }, {})
coalesceBadge({ color: '10ADED' }, { color: 'red' }, {}),
).to.include({ color: '10ADED' })
// also expected for legacy name
expect(
coalesceBadge({ colorB: 'B0ADED' }, { color: 'red' }, {})
coalesceBadge({ colorB: 'B0ADED' }, { color: 'red' }, {}),
).to.include({ color: 'B0ADED' })
})
@@ -68,16 +68,16 @@ describe('coalesceBadge', function () {
coalesceBadge(
{ color: '10ADED' },
{ isError: true, color: 'lightgray' },
{}
)
{},
),
).to.include({ color: 'lightgray' })
// also expected for legacy name
expect(
coalesceBadge(
{ colorB: 'B0ADED' },
{ isError: true, color: 'lightgray' },
{}
)
{},
),
).to.include({ color: 'lightgray' })
})
})
@@ -102,11 +102,11 @@ describe('coalesceBadge', function () {
it('overrides the label color', function () {
expect(
coalesceBadge({ labelColor: '42f483' }, { color: 'green' }, {})
coalesceBadge({ labelColor: '42f483' }, { color: 'green' }, {}),
).to.include({ labelColor: '42f483' })
// also expected for legacy name
expect(
coalesceBadge({ colorA: 'B2f483' }, { color: 'green' }, {})
coalesceBadge({ colorA: 'B2f483' }, { color: 'green' }, {}),
).to.include({ labelColor: 'B2f483' })
})
@@ -116,8 +116,8 @@ describe('coalesceBadge', function () {
// Scoutcamp converts numeric query params to numbers.
{ color: 123 },
{ color: 'green' },
{}
)
{},
),
).to.include({ color: '123' })
// also expected for legacy name
expect(
@@ -125,8 +125,8 @@ describe('coalesceBadge', function () {
// Scoutcamp converts numeric query params to numbers.
{ colorB: 123 },
{ color: 'green' },
{}
)
{},
),
).to.include({ color: '123' })
})
})
@@ -140,7 +140,7 @@ describe('coalesceBadge', function () {
it('when a social badge, uses the default named logo', function () {
// .not.be.empty for confidence that nothing has changed with `getShieldsIcon()`.
expect(
coalesceBadge({ style: 'social' }, {}, { namedLogo: 'appveyor' }).logo
coalesceBadge({ style: 'social' }, {}, { namedLogo: 'appveyor' }).logo,
).to.equal(getSimpleIcon({ name: 'appveyor' })).and.not.be.empty
})
@@ -149,28 +149,28 @@ describe('coalesceBadge', function () {
namedLogo: 'npm',
})
expect(coalesceBadge({}, { namedLogo: 'npm' }, {}).logo).to.equal(
getShieldsIcon({ name: 'npm' })
getShieldsIcon({ name: 'npm' }),
).and.not.to.be.empty
})
it('applies the named monochrome logo with color', function () {
expect(
coalesceBadge({}, { namedLogo: 'dependabot', logoColor: 'blue' }, {})
.logo
.logo,
).to.equal(getShieldsIcon({ name: 'dependabot', color: 'blue' })).and.not
.to.be.empty
})
it('applies the named multicolored logo with color', function () {
expect(
coalesceBadge({}, { namedLogo: 'npm', logoColor: 'blue' }, {}).logo
coalesceBadge({}, { namedLogo: 'npm', logoColor: 'blue' }, {}).logo,
).to.equal(getSimpleIcon({ name: 'npm', color: 'blue' })).and.not.to.be
.empty
})
it('overrides the logo', function () {
expect(
coalesceBadge({ logo: 'npm' }, { namedLogo: 'appveyor' }, {}).logo
coalesceBadge({ logo: 'npm' }, { namedLogo: 'appveyor' }, {}).logo,
).to.equal(getShieldsIcon({ name: 'npm' })).and.not.be.empty
})
@@ -179,8 +179,8 @@ describe('coalesceBadge', function () {
coalesceBadge(
{ logo: 'dependabot', logoColor: 'blue' },
{ namedLogo: 'appveyor' },
{}
).logo
{},
).logo,
).to.equal(getShieldsIcon({ name: 'dependabot', color: 'blue' })).and.not
.be.empty
})
@@ -190,8 +190,8 @@ describe('coalesceBadge', function () {
coalesceBadge(
{ logo: 'npm', logoColor: 'blue' },
{ namedLogo: 'appveyor' },
{}
).logo
{},
).logo,
).to.equal(getSimpleIcon({ name: 'npm', color: 'blue' })).and.not.be.empty
})
@@ -205,8 +205,8 @@ describe('coalesceBadge', function () {
logoPosition: -3,
logoWidth: 100,
},
{}
).logo
{},
).logo,
).to.equal(getShieldsIcon({ name: 'npm' })).and.not.be.empty
})
@@ -215,8 +215,8 @@ describe('coalesceBadge', function () {
coalesceBadge(
{ logoColor: 'blue' },
{ namedLogo: 'dependabot', logoColor: 'red' },
{}
).logo
{},
).logo,
).to.equal(getShieldsIcon({ name: 'dependabot', color: 'blue' })).and.not
.be.empty
})
@@ -226,8 +226,8 @@ describe('coalesceBadge', function () {
coalesceBadge(
{ logoColor: 'blue' },
{ namedLogo: 'npm', logoColor: 'red' },
{}
).logo
{},
).logo,
).to.equal(getSimpleIcon({ name: 'npm', color: 'blue' })).and.not.be.empty
})
@@ -235,7 +235,7 @@ describe('coalesceBadge', function () {
it('overrides logoSvg', function () {
const logoSvg = 'data:image/svg+xml;base64,PHN2ZyB4bWxu'
expect(coalesceBadge({ logo: 'npm' }, { logoSvg }, {}).logo).to.equal(
getShieldsIcon({ name: 'npm' })
getShieldsIcon({ name: 'npm' }),
).and.not.be.empty
})
})
@@ -244,7 +244,7 @@ describe('coalesceBadge', function () {
it('overrides the logo with custom svg', function () {
const logoSvg = 'data:image/svg+xml;base64,PHN2ZyB4bWxu'
expect(
coalesceBadge({ logo: logoSvg }, { namedLogo: 'appveyor' }, {})
coalesceBadge({ logo: logoSvg }, { namedLogo: 'appveyor' }, {}),
).to.include({ logo: logoSvg })
})
@@ -254,8 +254,8 @@ describe('coalesceBadge', function () {
coalesceBadge(
{ logo: logoSvg, logoColor: 'brightgreen' },
{ namedLogo: 'appveyor' },
{}
)
{},
),
).to.include({ logo: logoSvg })
})
})
@@ -269,7 +269,7 @@ describe('coalesceBadge', function () {
it('applies the logo width', function () {
expect(
coalesceBadge({}, { namedLogo: 'npm', logoWidth: 275 }, {})
coalesceBadge({}, { namedLogo: 'npm', logoWidth: 275 }, {}),
).to.include({ logoWidth: 275 })
})
})
@@ -283,7 +283,7 @@ describe('coalesceBadge', function () {
it('applies the logo position', function () {
expect(
coalesceBadge({}, { namedLogo: 'npm', logoPosition: -10 }, {})
coalesceBadge({}, { namedLogo: 'npm', logoPosition: -10 }, {}),
).to.include({ logoPosition: -10 })
})
})
@@ -296,8 +296,8 @@ describe('coalesceBadge', function () {
{
link: 'https://circleci.com/workflow-run/184ef3de-4836-4805-a2e4-0ceba099f92d',
},
{}
).links
{},
).links,
).to.deep.equal(['https://circleci.com/gh/badges/daily-tests'])
})
})
@@ -328,7 +328,7 @@ describe('coalesceBadge', function () {
describe('Cache length', function () {
it('overrides the cache length', function () {
expect(
coalesceBadge({ style: 'pill' }, { cacheSeconds: 123 }, {})
coalesceBadge({ style: 'pill' }, { cacheSeconds: 123 }, {}),
).to.include({ cacheLengthSeconds: 123 })
})
})

View File

@@ -20,7 +20,7 @@ function deprecatedService(attrs) {
const { route, name, label, category, examples, message } = Joi.attempt(
attrs,
attrSchema,
`Deprecated service for ${attrs.route.base}`
`Deprecated service for ${attrs.route.base}`,
)
return class DeprecatedService extends BaseService {

View File

@@ -6,7 +6,7 @@ import { makeFullUrl } from './route.js'
const optionalObjectOfKeyValues = Joi.object().pattern(
/./,
Joi.string().allow(null)
Joi.string().allow(null),
)
const schema = Joi.object({
@@ -32,19 +32,19 @@ function validateExample(example, index, ServiceClass) {
const result = Joi.attempt(
example,
schema,
`Example for ${ServiceClass.name} at index ${index}`
`Example for ${ServiceClass.name} at index ${index}`,
)
const { pattern, namedParams } = result
if (!pattern && !ServiceClass.route.pattern) {
throw new Error(
`Example for ${ServiceClass.name} at index ${index} does not declare a pattern`
`Example for ${ServiceClass.name} at index ${index} does not declare a pattern`,
)
}
if (pattern === ServiceClass.route.pattern) {
throw new Error(
`Example for ${ServiceClass.name} at index ${index} declares a redundant pattern which should be removed`
`Example for ${ServiceClass.name} at index ${index} declares a redundant pattern which should be removed`,
)
}
@@ -57,7 +57,7 @@ function validateExample(example, index, ServiceClass) {
throw Error(
`In example for ${
ServiceClass.name
} at index ${index}, ${e.message.toLowerCase()}`
} at index ${index}, ${e.message.toLowerCase()}`,
)
}
// Make sure there are no extra keys.
@@ -73,8 +73,8 @@ function validateExample(example, index, ServiceClass) {
`In example for ${
ServiceClass.name
} at index ${index}, namedParams contains unknown keys: ${extraKeys.join(
', '
)}`
', ',
)}`,
)
}
@@ -86,22 +86,22 @@ function validateExample(example, index, ServiceClass) {
`In example for ${
ServiceClass.name
} at index ${index}, keywords contains words that are less than two characters long: ${tinyKeywords.join(
', '
)}`
', ',
)}`,
)
}
// Make sure none of the keywords are already included in the title.
const title = (example.title || ServiceClass.name).toLowerCase()
const redundantKeywords = example.keywords.filter(k =>
title.includes(k.toLowerCase())
title.includes(k.toLowerCase()),
)
if (redundantKeywords.length) {
throw Error(
`In example for ${
ServiceClass.name
} at index ${index}, keywords contains words that are already in the title: ${redundantKeywords.join(
', '
)}`
', ',
)}`,
)
}
}
@@ -126,7 +126,7 @@ function transformExample(inExample, index, ServiceClass) {
{},
staticPreview,
ServiceClass.defaultBadgeData,
ServiceClass
ServiceClass,
)
const category = categories.find(c => c.id === ServiceClass.category)
@@ -135,7 +135,7 @@ function transformExample(inExample, index, ServiceClass) {
example: {
pattern: makeFullUrl(
ServiceClass.route.base,
pattern || ServiceClass.route.pattern
pattern || ServiceClass.route.pattern,
),
namedParams,
queryParams,

View File

@@ -16,7 +16,7 @@ describe('validateExample function', function () {
validExamples.forEach(example => {
expect(() =>
validateExample(example, 0, { route: {}, name: 'mockService' })
validateExample(example, 0, { route: {}, name: 'mockService' }),
).not.to.throw(Error)
})
})
@@ -66,7 +66,7 @@ describe('validateExample function', function () {
invalidExamples.forEach(example => {
expect(() =>
validateExample(example, 0, { route: {}, name: 'mockService' })
validateExample(example, 0, { route: {}, name: 'mockService' }),
).to.throw(Error)
})
})
@@ -93,7 +93,7 @@ test(transformExample, function () {
keywords: ['hello'],
},
0,
ExampleService
ExampleService,
).expect({
title: 'ExampleService',
example: {
@@ -119,7 +119,7 @@ test(transformExample, function () {
keywords: ['hello'],
},
0,
ExampleService
ExampleService,
).expect({
title: 'ExampleService',
example: {
@@ -146,7 +146,7 @@ test(transformExample, function () {
keywords: ['hello'],
},
0,
ExampleService
ExampleService,
).expect({
title: 'ExampleService',
example: {

View File

@@ -21,7 +21,7 @@ describe('got wrapper', function () {
.reply(200, 'x'.repeat(101))
const sendRequest = _fetchFactory(100)
return expect(
sendRequest('https://www.google.com/foo/bar')
sendRequest('https://www.google.com/foo/bar'),
).to.be.rejectedWith(InvalidResponse, 'Maximum response size exceeded')
})
@@ -29,7 +29,7 @@ describe('got wrapper', function () {
nock('https://www.google.com').get('/foo/bar').replyWithError('oh no')
const sendRequest = _fetchFactory(1024)
return expect(
sendRequest('https://www.google.com/foo/bar')
sendRequest('https://www.google.com/foo/bar'),
).to.be.rejectedWith(Inaccessible, 'oh no')
})
@@ -38,10 +38,10 @@ describe('got wrapper', function () {
nock.disableNetConnect()
const sendRequest = _fetchFactory(1024)
return expect(
sendRequest('https://www.google.com/foo/bar')
sendRequest('https://www.google.com/foo/bar'),
).to.be.rejectedWith(
Inaccessible,
'Nock: Disallowed net connect for "www.google.com:443/foo/bar"'
'Nock: Disallowed net connect for "www.google.com:443/foo/bar"',
)
})
@@ -57,18 +57,18 @@ describe('got wrapper', function () {
prettyMessage: 'Oh no! A terrible thing has happened',
cacheSeconds: 10,
},
}
)
},
),
)
.to.be.rejectedWith(
Inaccessible,
"Inaccessible: Timeout awaiting 'request' for 1ms"
"Inaccessible: Timeout awaiting 'request' for 1ms",
)
// eslint-disable-next-line promise/prefer-await-to-then
.then(error => {
expect(error).to.have.property(
'prettyMessage',
'Oh no! A terrible thing has happened'
'Oh no! A terrible thing has happened',
)
expect(error).to.have.property('cacheSeconds', 10)
})

View File

@@ -9,18 +9,16 @@ describe('mergeQueries function', function () {
it('merges valid gql queries', function () {
expect(
print(
mergeQueries(
gql`
query ($param: String!) {
foo(param: $param) {
bar
}
mergeQueries(gql`
query ($param: String!) {
foo(param: $param) {
bar
}
`
)
)
}
`),
),
).to.equalIgnoreSpaces(
'query ($param: String!) { foo(param: $param) { bar } }'
'query ($param: String!) { foo(param: $param) { bar } }',
)
expect(
@@ -37,11 +35,11 @@ describe('mergeQueries function', function () {
query {
baz
}
`
)
)
`,
),
),
).to.equalIgnoreSpaces(
'query ($param: String!) { foo(param: $param) { bar } baz }'
'query ($param: String!) { foo(param: $param) { bar } baz }',
)
expect(
@@ -61,9 +59,9 @@ describe('mergeQueries function', function () {
query {
baz
}
`
)
)
`,
),
),
).to.equalIgnoreSpaces('{ foo bar baz }')
expect(
@@ -78,9 +76,9 @@ describe('mergeQueries function', function () {
{
bar
}
`
)
)
`,
),
),
).to.equalIgnoreSpaces('{ foo bar }')
})

View File

@@ -15,6 +15,7 @@ import {
Deprecated,
ImproperlyConfigured,
} from './errors.js'
import { pathParam, pathParams, queryParam, queryParams } from './openapi.js'
export {
BaseService,
@@ -32,4 +33,8 @@ export {
InvalidParameter,
ImproperlyConfigured,
Deprecated,
pathParam,
pathParams,
queryParam,
queryParams,
}

View File

@@ -104,7 +104,7 @@ function handleRequest(cacheHeaderConfig, handlerOptions) {
const badgeData = coalesceBadge(
filteredQueryParams,
{ label: 'vendor', message: 'unresponsive' },
{}
{},
)
const svg = makeBadge(badgeData)
const extension = (match.slice(-1)[0] || '.svg').replace(/^\./, '')
@@ -126,7 +126,7 @@ function handleRequest(cacheHeaderConfig, handlerOptions) {
const svg = makeBadge(badgeData)
setCacheHeadersOnResponse(ask.res, badgeData.cacheLengthSeconds)
makeSend(format, ask.res, end)(svg)
}
},
)
// eslint-disable-next-line promise/prefer-await-to-then
if (result && result.catch) {

View File

@@ -18,7 +18,7 @@ function fakeHandler(queryParams, match, sendBadge, request) {
label: 'testing',
message: someValue,
},
{}
{},
)
sendBadge(format, badgeData)
}
@@ -35,7 +35,7 @@ function createFakeHandlerWithCacheLength(cacheLengthSeconds) {
{},
{
_cacheLength: cacheLengthSeconds,
}
},
)
sendBadge(format, badgeData)
}
@@ -66,7 +66,7 @@ describe('The request handler', function () {
beforeEach(function () {
camp.route(
/^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
handleRequest(standardCacheHeaders, { handler: fakeHandler })
handleRequest(standardCacheHeaders, { handler: fakeHandler }),
)
})
@@ -90,7 +90,7 @@ describe('The request handler', function () {
beforeEach(function () {
camp.route(
/^\/testing\/([^/]+)\.(svg|png|gif|jpg|json)$/,
handleRequest(standardCacheHeaders, fakeHandler)
handleRequest(standardCacheHeaders, fakeHandler),
)
})
@@ -119,8 +119,8 @@ describe('The request handler', function () {
cacheHeaderConfig,
(queryParams, match, sendBadge, request) => {
fakeHandler(queryParams, match, sendBadge, request)
}
)
},
),
)
}
@@ -128,7 +128,7 @@ describe('The request handler', function () {
register({ cacheHeaderConfig: { defaultCacheLengthSeconds: 900 } })
const { headers } = await got(`${baseUrl}/testing/123.json`)
const expectedExpiry = new Date(
+new Date(headers.date) + 900000
+new Date(headers.date) + 900000,
).toGMTString()
expect(headers.expires).to.equal(expectedExpiry)
expect(headers['cache-control']).to.equal('max-age=900, s-maxage=900')
@@ -142,7 +142,7 @@ describe('The request handler', function () {
const { headers } = await got(`${baseUrl}/testing/123.json`)
const expectedExpiry = new Date(
+new Date(headers.date) + 900000
+new Date(headers.date) + 900000,
).toGMTString()
expect(headers.expires).to.equal(expectedExpiry)
expect(headers['cache-control']).to.equal('max-age=900, s-maxage=900')
@@ -158,10 +158,10 @@ describe('The request handler', function () {
queryParams,
match,
sendBadge,
request
request,
)
}
)
},
),
)
const { headers } = await got(`${baseUrl}/testing/123.json`)
@@ -178,10 +178,10 @@ describe('The request handler', function () {
queryParams,
match,
sendBadge,
request
request,
)
}
)
},
),
)
const { headers } = await got(`${baseUrl}/testing/123.json`)
@@ -191,10 +191,10 @@ describe('The request handler', function () {
it('should set the expires header to current time + cacheSeconds', async function () {
register({ cacheHeaderConfig: { defaultCacheLengthSeconds: 0 } })
const { headers } = await got(
`${baseUrl}/testing/123.json?cacheSeconds=3600`
`${baseUrl}/testing/123.json?cacheSeconds=3600`,
)
const expectedExpiry = new Date(
+new Date(headers.date) + 3600000
+new Date(headers.date) + 3600000,
).toGMTString()
expect(headers.expires).to.equal(expectedExpiry)
expect(headers['cache-control']).to.equal('max-age=3600, s-maxage=3600')
@@ -203,10 +203,10 @@ describe('The request handler', function () {
it('should ignore cacheSeconds when shorter than defaultCacheLengthSeconds', async function () {
register({ cacheHeaderConfig: { defaultCacheLengthSeconds: 600 } })
const { headers } = await got(
`${baseUrl}/testing/123.json?cacheSeconds=300`
`${baseUrl}/testing/123.json?cacheSeconds=300`,
)
const expectedExpiry = new Date(
+new Date(headers.date) + 600000
+new Date(headers.date) + 600000,
).toGMTString()
expect(headers.expires).to.equal(expectedExpiry)
expect(headers['cache-control']).to.equal('max-age=600, s-maxage=600')
@@ -217,7 +217,7 @@ describe('The request handler', function () {
const { headers } = await got(`${baseUrl}/testing/123.json`)
expect(headers.expires).to.equal(headers.date)
expect(headers['cache-control']).to.equal(
'no-cache, no-store, must-revalidate'
'no-cache, no-store, must-revalidate',
)
})
})
@@ -234,7 +234,7 @@ describe('The request handler', function () {
++handlerCallCount
fakeHandler(queryParams, match, sendBadge, request)
},
})
}),
)
})
@@ -242,7 +242,7 @@ describe('The request handler', function () {
await performTwoRequests(
baseUrl,
'/testing/123.svg?foo=1',
'/testing/123.svg?foo=2'
'/testing/123.svg?foo=2',
)
expect(handlerCallCount).to.equal(2)
})

View File

@@ -10,7 +10,7 @@ const serviceDir = path.join(
path.dirname(fileURLToPath(import.meta.url)),
'..',
'..',
'services'
'services',
)
function toUnixPath(path) {
@@ -51,14 +51,14 @@ async function loadServiceClasses(servicePaths) {
const serviceClasses = []
for await (const servicePath of servicePaths) {
const currentServiceClasses = Object.values(
await import(`file://${servicePath}`)
await import(`file://${servicePath}`),
).flatMap(element =>
typeof element === 'object' ? Object.values(element) : element
typeof element === 'object' ? Object.values(element) : element,
)
if (currentServiceClasses.length === 0) {
throw new InvalidService(
`Expected ${servicePath} to export a service or a collection of services`
`Expected ${servicePath} to export a service or a collection of services`,
)
}
currentServiceClasses.forEach(serviceClass => {
@@ -71,7 +71,7 @@ async function loadServiceClasses(servicePaths) {
return serviceClasses.push(serviceClass)
}
throw new InvalidService(
`Expected ${servicePath} to export a service or a collection of services; one of them was ${serviceClass}`
`Expected ${servicePath} to export a service or a collection of services; one of them was ${serviceClass}`,
)
})
}
@@ -80,9 +80,21 @@ async function loadServiceClasses(servicePaths) {
serviceClasses.map(({ name }) => name),
{
message: 'Duplicate service names found',
}
},
)
const routeSummaries = []
serviceClasses.forEach(function (serviceClass) {
if (serviceClass.openApi) {
for (const route of Object.values(serviceClass.openApi)) {
routeSummaries.push(route.get.summary)
}
}
})
assertNamesUnique(routeSummaries, {
message: 'Duplicate route summary found',
})
return serviceClasses
}
@@ -102,8 +114,8 @@ async function collectDefinitions() {
async function loadTesters() {
return Promise.all(
getServicePaths('*.tester.js').map(
async path => await import(`file://${path}`)
)
async path => await import(`file://${path}`),
),
)
}

View File

@@ -12,50 +12,56 @@ chai.use(chaiAsPromised)
const { expect } = chai
const fixturesDir = path.join(
path.dirname(fileURLToPath(import.meta.url)),
'loader-test-fixtures'
'loader-test-fixtures',
)
describe('loadServiceClasses function', function () {
it('throws if module exports empty', async function () {
await expect(
loadServiceClasses([path.join(fixturesDir, 'empty-undefined.fixture.js')])
loadServiceClasses([
path.join(fixturesDir, 'empty-undefined.fixture.js'),
]),
).to.be.rejectedWith(InvalidService)
await expect(
loadServiceClasses([path.join(fixturesDir, 'empty-array.fixture.js')])
loadServiceClasses([path.join(fixturesDir, 'empty-array.fixture.js')]),
).to.be.rejectedWith(InvalidService)
await expect(
loadServiceClasses([path.join(fixturesDir, 'empty-object.fixture.js')])
loadServiceClasses([path.join(fixturesDir, 'empty-object.fixture.js')]),
).to.be.rejectedWith(InvalidService)
await expect(
loadServiceClasses([path.join(fixturesDir, 'empty-no-export.fixture.js')])
loadServiceClasses([
path.join(fixturesDir, 'empty-no-export.fixture.js'),
]),
).to.be.rejectedWith(InvalidService)
await expect(
loadServiceClasses([
path.join(fixturesDir, 'valid-array.fixture.js'),
path.join(fixturesDir, 'valid-class.fixture.js'),
path.join(fixturesDir, 'empty-array.fixture.js'),
])
]),
).to.be.rejectedWith(InvalidService)
})
it('throws if module exports invalid', async function () {
await expect(
loadServiceClasses([path.join(fixturesDir, 'invalid-no-base.fixture.js')])
loadServiceClasses([
path.join(fixturesDir, 'invalid-no-base.fixture.js'),
]),
).to.be.rejectedWith(InvalidService)
await expect(
loadServiceClasses([
path.join(fixturesDir, 'invalid-wrong-base.fixture.js'),
])
]),
).to.be.rejectedWith(InvalidService)
await expect(
loadServiceClasses([path.join(fixturesDir, 'invalid-mixed.fixture.js')])
loadServiceClasses([path.join(fixturesDir, 'invalid-mixed.fixture.js')]),
).to.be.rejectedWith(InvalidService)
await expect(
loadServiceClasses([
path.join(fixturesDir, 'valid-array.fixture.js'),
path.join(fixturesDir, 'valid-class.fixture.js'),
path.join(fixturesDir, 'invalid-no-base.fixture.js'),
])
]),
).to.be.rejectedWith(InvalidService)
})
@@ -65,7 +71,7 @@ describe('loadServiceClasses function', function () {
path.join(fixturesDir, 'valid-array.fixture.js'),
path.join(fixturesDir, 'valid-object.fixture.js'),
path.join(fixturesDir, 'valid-class.fixture.js'),
])
]),
).to.eventually.have.length(5)
})
})

View File

@@ -1,3 +1,9 @@
/**
* Functions for publishing the shields.io URL schema as an OpenAPI Document
*
* @module
*/
const baseUrl = process.env.BASE_URL
const globalParamRefs = [
{ $ref: '#/components/parameters/style' },
@@ -158,7 +164,7 @@ function examples2openapi(examples) {
const parameters = [
...pathParams,
...Object.entries(queryParams).map(([paramName, exampleValue]) =>
param2openapi(pattern, paramName, exampleValue, 'query')
param2openapi(pattern, paramName, exampleValue, 'query'),
),
...globalParamRefs,
]
@@ -198,7 +204,7 @@ function services2openapi(services) {
if (service.openApi) {
// if the service declares its own OpenAPI definition, use that...
for (const [key, value] of Object.entries(
addGlobalProperties(service.openApi)
addGlobalProperties(service.openApi),
)) {
if (key in paths) {
throw new Error(`Conflicting route: ${key}`)
@@ -208,7 +214,7 @@ function services2openapi(services) {
} else {
// ...otherwise do our best to build one from examples[]
for (const [key, value] of Object.entries(
examples2openapi(service.examples)
examples2openapi(service.examples),
)) {
// allow conflicting routes for legacy examples
paths[key] = value
@@ -247,7 +253,7 @@ function category2openapi(category, services) {
in: 'query',
required: false,
description:
'One of the named logos (bitcoin, dependabot, gitlab, npm, paypal, serverfault, stackexchange, superuser, telegram, travis) or simple-icons. All simple-icons are referenced using icon slugs. You can click the icon title on <a href="https://simpleicons.org/" rel="noopener noreferrer" target="_blank">simple-icons</a> to copy the slug or they can be found in the <a href="https://github.com/simple-icons/simple-icons/blob/master/slugs.md">slugs.md file</a> in the simple-icons repository.',
'One of the named logos (bitcoin, dependabot, gitlab, npm, paypal, serverfault, stackexchange, superuser, telegram, travis) or simple-icons. All simple-icons are referenced using icon slugs. You can click the icon title on <a href="https://simpleicons.org/" rel="noopener noreferrer" target="_blank">simple-icons</a> to copy the slug or they can be found in the <a href="https://github.com/simple-icons/simple-icons/blob/master/slugs.md">slugs.md file</a> in the simple-icons repository. <a href="/docs/logos">Further info</a>.',
schema: {
type: 'string',
},
@@ -332,4 +338,132 @@ function category2openapi(category, services) {
return spec
}
export { category2openapi }
/**
* Helper function for assembling an OpenAPI path parameter object
*
* @param {module:core/base-service/openapi~PathParamInput} param Input param
* @returns {module:core/base-service/openapi~OpenApiParam} OpenAPI Parameter Object
* @see https://swagger.io/specification/#parameter-object
*/
function pathParam({
name,
example,
schema = { type: 'string' },
description,
}) {
return { name, in: 'path', required: true, schema, example, description }
}
/**
* Helper function for assembling an array of OpenAPI path parameter objects
* The code
* ```
* const params = pathParams(
* { name: 'name1', example: 'example1' },
* { name: 'name2', example: 'example2' },
* )
* ```
* is equivilent to
* ```
* const params = [
* pathParam({ name: 'name1', example: 'example1' }),
* pathParam({ name: 'name2', example: 'example2' }),
* ]
* ```
*
* @param {...module:core/base-service/openapi~PathParamInput} params Input params
* @returns {Array.<module:core/base-service/openapi~OpenApiParam>} Array of OpenAPI Parameter Objects
* @see {@link module:core/base-service/openapi~pathParam}
*/
function pathParams(...params) {
return params.map(param => pathParam(param))
}
/**
* Helper function for assembling an OpenAPI query parameter object
*
* @param {module:core/base-service/openapi~QueryParamInput} param Input param
* @returns {module:core/base-service/openapi~OpenApiParam} OpenAPI Parameter Object
* @see https://swagger.io/specification/#parameter-object
*/
function queryParam({
name,
example,
schema = { type: 'string' },
required = false,
description,
}) {
const param = { name, in: 'query', required, schema, example, description }
if (example === null && schema.type === 'boolean') {
param.allowEmptyValue = true
}
return param
}
/**
* Helper function for assembling an array of OpenAPI query parameter objects
* The code
* ```
* const params = queryParams(
* { name: 'name1', example: 'example1' },
* { name: 'name2', example: 'example2' },
* )
* ```
* is equivilent to
* ```
* const params = [
* queryParam({ name: 'name1', example: 'example1' }),
* queryParams({ name: 'name2', example: 'example2' }),
* ]
* ```
*
* @param {...module:core/base-service/openapi~QueryParamInput} params Input params
* @returns {Array.<module:core/base-service/openapi~OpenApiParam>} Array of OpenAPI Parameter Objects
* @see {@link module:core/base-service/openapi~queryParam}
*/
function queryParams(...params) {
return params.map(param => queryParam(param))
}
/**
* @typedef {object} PathParamInput
* @property {string} name The name of the parameter. Parameter names are case sensitive
* @property {string} example Example of a valid value for this parameter
* @property {object} [schema={ type: 'string' }] Parameter schema.
* An [OpenAPI Schema object](https://swagger.io/specification/#schema-object)
* specifying the parameter type.
* Normally this should be omitted as all path parameters are strings.
* Use this when we also want to pass an enum of valid parameters
* to be presented as a drop-down in the frontend. e.g:
* `{'type': 'string', 'enum': ['github', 'bitbucket'}` (Optional)
* @property {string} description A brief description of the parameter (Optional)
*/
/**
* @typedef {object} QueryParamInput
* @property {string} name The name of the parameter. Parameter names are case sensitive
* @property {string|null} example Example of a valid value for this parameter
* @property {object} [schema={ type: 'string' }] Parameter schema.
* An [OpenAPI Schema object](https://swagger.io/specification/#schema-object)
* specifying the parameter type. This can normally be omitted.
* Query params are usually strings. (Optional)
* @property {boolean} [required=false] Determines whether this parameter is mandatory (Optional)
* @property {string} description A brief description of the parameter (Optional)
*/
/**
* OpenAPI Parameter Object
*
* @typedef {object} OpenApiParam
* @property {string} name The name of the parameter
* @property {string|null} example Example of a valid value for this parameter
* @property {('path'|'query')} in The location of the parameter
* @property {object} schema Parameter schema.
* An [OpenAPI Schema object](https://swagger.io/specification/#schema-object)
* specifying the parameter type.
* @property {boolean} required Determines whether this parameter is mandatory
* @property {string} description A brief description of the parameter
* @property {boolean} allowEmptyValue If true, allows the ability to pass an empty value to this parameter
*/
export { category2openapi, pathParam, pathParams, queryParam, queryParams }

View File

@@ -1,5 +1,11 @@
import chai from 'chai'
import { category2openapi } from './openapi.js'
import {
category2openapi,
pathParam,
pathParams,
queryParam,
queryParams,
} from './openapi.js'
import BaseJsonService from './base-json.js'
const { expect } = chai
@@ -92,7 +98,7 @@ const expected = {
in: 'query',
required: false,
description:
'One of the named logos (bitcoin, dependabot, gitlab, npm, paypal, serverfault, stackexchange, superuser, telegram, travis) or simple-icons. All simple-icons are referenced using icon slugs. You can click the icon title on <a href="https://simpleicons.org/" rel="noopener noreferrer" target="_blank">simple-icons</a> to copy the slug or they can be found in the <a href="https://github.com/simple-icons/simple-icons/blob/master/slugs.md">slugs.md file</a> in the simple-icons repository.',
'One of the named logos (bitcoin, dependabot, gitlab, npm, paypal, serverfault, stackexchange, superuser, telegram, travis) or simple-icons. All simple-icons are referenced using icon slugs. You can click the icon title on <a href="https://simpleicons.org/" rel="noopener noreferrer" target="_blank">simple-icons</a> to copy the slug or they can be found in the <a href="https://github.com/simple-icons/simple-icons/blob/master/slugs.md">slugs.md file</a> in the simple-icons repository. <a href="/docs/logos">Further info</a>.',
schema: { type: 'string' },
example: 'appveyor',
},
@@ -371,8 +377,153 @@ describe('category2openapi', function () {
category2openapi({ name: 'build' }, [
OpenApiService.getDefinition(),
LegacyService.getDefinition(),
])
)
]),
),
).to.deep.equal(expected)
})
})
describe('pathParam, pathParams', function () {
it('generates a pathParam with defaults', function () {
const input = { name: 'name', example: 'example' }
const expected = {
name: 'name',
in: 'path',
required: true,
schema: {
type: 'string',
},
example: 'example',
description: undefined,
}
expect(pathParam(input)).to.deep.equal(expected)
expect(pathParams(input)[0]).to.deep.equal(expected)
})
it('generates a pathParam with custom args', function () {
const input = {
name: 'name',
example: true,
schema: { type: 'boolean' },
description: 'long desc',
}
const expected = {
name: 'name',
in: 'path',
required: true,
schema: {
type: 'boolean',
},
example: true,
description: 'long desc',
}
expect(pathParam(input)).to.deep.equal(expected)
expect(pathParams(input)[0]).to.deep.equal(expected)
})
it('generates multiple pathParams', function () {
expect(
pathParams(
{ name: 'name1', example: 'example1' },
{ name: 'name2', example: 'example2' },
),
).to.deep.equal([
{
name: 'name1',
in: 'path',
required: true,
schema: {
type: 'string',
},
example: 'example1',
description: undefined,
},
{
name: 'name2',
in: 'path',
required: true,
schema: {
type: 'string',
},
example: 'example2',
description: undefined,
},
])
})
})
describe('queryParam, queryParams', function () {
it('generates a queryParam with defaults', function () {
const input = { name: 'name', example: 'example' }
const expected = {
name: 'name',
in: 'query',
required: false,
schema: { type: 'string' },
example: 'example',
description: undefined,
}
expect(queryParam(input)).to.deep.equal(expected)
expect(queryParams(input)[0]).to.deep.equal(expected)
})
it('generates queryParam with custom args', function () {
const input = {
name: 'name',
example: 'example',
required: true,
description: 'long desc',
}
const expected = {
name: 'name',
in: 'query',
required: true,
schema: { type: 'string' },
example: 'example',
description: 'long desc',
}
expect(queryParam(input)).to.deep.equal(expected)
expect(queryParams(input)[0]).to.deep.equal(expected)
})
it('generates a queryParam with boolean/null example', function () {
const input = { name: 'name', example: null, schema: { type: 'boolean' } }
const expected = {
name: 'name',
in: 'query',
required: false,
schema: { type: 'boolean' },
allowEmptyValue: true,
example: null,
description: undefined,
}
expect(queryParam(input)).to.deep.equal(expected)
expect(queryParams(input)[0]).to.deep.equal(expected)
})
it('generates multiple queryParams', function () {
expect(
queryParams(
{ name: 'name1', example: 'example1' },
{ name: 'name2', example: 'example2' },
),
).to.deep.equal([
{
name: 'name1',
in: 'query',
required: false,
schema: { type: 'string' },
example: 'example1',
description: undefined,
},
{
name: 'name2',
in: 'query',
required: false,
schema: { type: 'string' },
example: 'example2',
description: undefined,
},
])
})
})

View File

@@ -23,7 +23,7 @@ const attrSchema = Joi.object({
.required()
.error(
() =>
'"transformPath" must be a function that transforms named params to a new path'
'"transformPath" must be a function that transforms named params to a new path',
),
transformQueryParams: Joi.func().arity(1),
dateAdded: Joi.date().required(),
@@ -80,7 +80,7 @@ export default function redirector(attrs) {
'inbound',
emojic.arrowHeadingUp,
'Redirector',
route.base
route.base,
)
trace.logTrace('inbound', emojic.ticket, 'Named params', namedParams)
trace.logTrace('inbound', emojic.crayon, 'Query params', queryParams)

View File

@@ -27,7 +27,7 @@ describe('Redirector', function () {
redirector({
...attrs,
name: 'ShinyRedirect',
}).name
}).name,
).to.equal('ShinyRedirect')
})
@@ -41,7 +41,7 @@ describe('Redirector', function () {
it('throws the expected error when dateAdded is missing', function () {
expect(() =>
redirector({ route, category, transformPath }).validateDefinition()
redirector({ route, category, transformPath }).validateDefinition(),
).to.throw('"dateAdded" is required')
})
@@ -93,7 +93,7 @@ describe('Redirector', function () {
})
ServiceClass.register(
{ camp },
{ rasterUrl: 'http://raster.example.test' }
{ rasterUrl: 'http://raster.example.test' },
)
})
@@ -102,7 +102,7 @@ describe('Redirector', function () {
`${baseUrl}/very/old/service/hello-world.svg`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
@@ -114,12 +114,12 @@ describe('Redirector', function () {
`${baseUrl}/very/old/service/hello-world.png`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
expect(headers.location).to.equal(
'http://raster.example.test/new/service/hello-world.png'
'http://raster.example.test/new/service/hello-world.png',
)
})
@@ -128,12 +128,12 @@ describe('Redirector', function () {
`${baseUrl}/very/old/service/hello-world.svg?color=123&style=flat-square`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
expect(headers.location).to.equal(
'/new/service/hello-world.svg?color=123&style=flat-square'
'/new/service/hello-world.svg?color=123&style=flat-square',
)
})
@@ -142,12 +142,12 @@ describe('Redirector', function () {
`${baseUrl}/very/old/service/hello%0Dworld.svg?foobar=a%0Db`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
expect(headers.location).to.equal(
'/new/service/hello%0Dworld.svg?foobar=a%0Db'
'/new/service/hello%0Dworld.svg?foobar=a%0Db',
)
})
@@ -174,12 +174,12 @@ describe('Redirector', function () {
`${baseUrl}/another/old/service/token/abc123/hello-world.svg`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
expect(headers.location).to.equal(
'/new/service/hello-world.svg?token=abc123'
'/new/service/hello-world.svg?token=abc123',
)
})
@@ -188,12 +188,12 @@ describe('Redirector', function () {
`${baseUrl}/another/old/service/token/abc123/hello-world.svg?color=123&style=flat-square`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
expect(headers.location).to.equal(
'/new/service/hello-world.svg?color=123&style=flat-square&token=abc123'
'/new/service/hello-world.svg?color=123&style=flat-square&token=abc123',
)
})
@@ -202,12 +202,12 @@ describe('Redirector', function () {
`${baseUrl}/another/old/service/token/abc123/hello-world.svg?color=123&style=flat-square&token=def456`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
expect(headers.location).to.equal(
'/new/service/hello-world.svg?color=123&style=flat-square&token=abc123'
'/new/service/hello-world.svg?color=123&style=flat-square&token=abc123',
)
})
@@ -229,12 +229,12 @@ describe('Redirector', function () {
`${baseUrl}/override/service/token/abc123/hello-world.svg?style=flat-square&token=def456`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
expect(headers.location).to.equal(
'/new/service/hello-world.svg?style=flat-square&token=def456'
'/new/service/hello-world.svg?style=flat-square&token=def456',
)
})
})

View File

@@ -40,7 +40,7 @@ async function getCachedResource({
}
const { buffer } = await checkErrorResponse({})(
await requestFetcher(url, options)
await requestFetcher(url, options),
)
let reqData

View File

@@ -52,7 +52,7 @@ function namedParamsForMatch(captureNames = [], match, ServiceClass) {
if (captureNames.length !== captures.length) {
throw new Error(
`Service ${ServiceClass.name} declares incorrect number of named params ` +
`(expected ${captures.length}, got ${captureNames.length})`
`(expected ${captures.length}, got ${captureNames.length})`,
)
}

View File

@@ -86,9 +86,9 @@ describe('Route helpers', function () {
expect(() =>
namedParamsForMatch(captureNames, regex.exec('/foo/bar/baz.svg'), {
name: 'MyService',
})
}),
).to.throw(
'Service MyService declares incorrect number of named params (expected 2, got 1)'
'Service MyService declares incorrect number of named params (expected 2, got 1)',
)
})
@@ -96,14 +96,14 @@ describe('Route helpers', function () {
expect(
getQueryParamNames({
queryParamSchema: Joi.object({ foo: Joi.string() }).required(),
})
}),
).to.deep.equal(['foo'])
expect(
getQueryParamNames({
queryParamSchema: Joi.object({ foo: Joi.string() })
.rename('bar', 'foo', { ignoreUndefined: true, override: true })
.required(),
})
}),
).to.deep.equal(['foo', 'bar'])
})
})

View File

@@ -18,7 +18,7 @@ const serviceDefinition = Joi.object({
Joi.object({
format: Joi.string().required(),
queryParams: arrayOfStrings,
})
}),
),
examples: Joi.array()
.items(
@@ -40,7 +40,7 @@ const serviceDefinition = Joi.object({
documentation: Joi.object({
__html: Joi.string().required(), // Valid HTML.
}),
})
}),
)
.default([]),
openApi: Joi.object().pattern(
@@ -48,7 +48,7 @@ const serviceDefinition = Joi.object({
Joi.object({
get: Joi.object({
summary: Joi.string().required(),
description: Joi.string().required(),
description: Joi.string(),
parameters: Joi.array()
.items(
Joi.object({
@@ -56,19 +56,23 @@ const serviceDefinition = Joi.object({
description: Joi.string(),
in: Joi.string().valid('query', 'path').required(),
required: Joi.boolean().required(),
schema: Joi.object({ type: Joi.string().required() }).required(),
example: Joi.string(),
})
schema: Joi.object({
type: Joi.string().required(),
enum: Joi.array(),
}).required(),
allowEmptyValue: Joi.boolean(),
example: Joi.string().allow(null),
}),
)
.min(1)
.required(),
}).required(),
}).required()
}).required(),
),
}).required()
function assertValidServiceDefinition(example, message = undefined) {
Joi.assert(example, serviceDefinition, message)
function assertValidServiceDefinition(service, message = undefined) {
Joi.assert(service, serviceDefinition, message)
}
const serviceDefinitionExport = Joi.object({
@@ -79,7 +83,7 @@ const serviceDefinitionExport = Joi.object({
id: Joi.string().required(),
name: Joi.string().required(),
keywords: arrayOfStrings,
})
}),
)
.required(),
services: Joi.array().items(serviceDefinition).required(),

View File

@@ -12,7 +12,7 @@ function validate(
allowAndStripUnknownKeys = true,
},
data,
schema
schema,
) {
if (!schema || !Joi.isSchema(schema)) {
throw Error('A Joi schema is required')
@@ -28,7 +28,7 @@ function validate(
'validate',
emojic.womanShrugging,
traceErrorMessage,
error.message
error.message,
)
let prettyMessage = prettyErrorMessage

View File

@@ -49,7 +49,7 @@ describe('validate', function () {
sinon.match.string,
traceSuccessMessage,
{ requiredString: 'bar' },
{ deep: true }
{ deep: true },
)
})
})
@@ -60,13 +60,13 @@ describe('validate', function () {
validate(
options,
{ requiredString: ['this', "shouldn't", 'work'] },
schema
schema,
)
expect.fail('Expected to throw')
} catch (e) {
expect(e).to.be.an.instanceof(InvalidParameter)
expect(e.message).to.equal(
'Invalid Parameter: "requiredString" must be a string'
'Invalid Parameter: "requiredString" must be a string',
)
expect(e.prettyMessage).to.equal(prettyErrorMessage)
}
@@ -74,7 +74,7 @@ describe('validate', function () {
'validate',
sinon.match.string,
traceErrorMessage,
'"requiredString" must be a string'
'"requiredString" must be a string',
)
})
@@ -86,16 +86,16 @@ describe('validate', function () {
{
requiredString: ['this', "shouldn't", 'work'],
},
schema
schema,
)
expect.fail('Expected to throw')
} catch (e) {
expect(e).to.be.an.instanceof(InvalidParameter)
expect(e.message).to.equal(
'Invalid Parameter: "requiredString" must be a string'
'Invalid Parameter: "requiredString" must be a string',
)
expect(e.prettyMessage).to.equal(
`${prettyErrorMessage}: requiredString`
`${prettyErrorMessage}: requiredString`,
)
}
})
@@ -107,13 +107,13 @@ describe('validate', function () {
validate(
{ ...options, allowAndStripUnknownKeys: false, includeKeys: true },
{ requiredString: 'bar', extra: 'nonsense', more: 'bogus' },
schema
schema,
)
expect.fail('Expected to throw')
} catch (e) {
expect(e).to.be.an.instanceof(InvalidParameter)
expect(e.message).to.equal(
'Invalid Parameter: "extra" is not allowed. "more" is not allowed'
'Invalid Parameter: "extra" is not allowed. "more" is not allowed',
)
expect(e.prettyMessage).to.equal(`${prettyErrorMessage}: extra, more`)
}

View File

@@ -27,14 +27,16 @@ export default class InfluxMetrics {
response = await got.post(request)
} catch (error) {
log.error(
new Error(`Cannot push metrics. Cause: ${error.name}: ${error.message}`)
new Error(
`Cannot push metrics. Cause: ${error.name}: ${error.message}`,
),
)
}
if (response && response.statusCode >= 300) {
log.error(
new Error(
`Cannot push metrics. ${request.url} responded with status code ${response.statusCode}`
)
`Cannot push metrics. ${request.url} responded with status code ${response.statusCode}`,
),
)
}
}
@@ -42,7 +44,7 @@ export default class InfluxMetrics {
startPushingMetrics() {
this._intervalId = setInterval(
() => this.sendMetrics(),
this._config.intervalSeconds * 1000
this._config.intervalSeconds * 1000,
)
}

View File

@@ -47,7 +47,7 @@ describe('Influx metrics', function () {
const influxMetrics = new InfluxMetrics(metricInstance, customConfig)
expect(await influxMetrics.metrics()).to.be.contain(
'instance=test-hostname'
'instance=test-hostname',
)
})
@@ -69,7 +69,7 @@ describe('Influx metrics', function () {
const influxMetrics = new InfluxMetrics(metricInstance, customConfig)
expect(await influxMetrics.metrics()).to.be.contain(
'instance=test-hostname-alias'
'instance=test-hostname-alias',
)
})
})
@@ -96,7 +96,7 @@ describe('Influx metrics', function () {
.persist()
.post(
'/metrics',
'prometheus,application=shields,env=test-env,instance=instance2 counter1=11'
'prometheus,application=shields,env=test-env,instance=instance2 counter1=11',
)
.basicAuth({ user: 'metrics-username', pass: 'metrics-password' })
.reply(200)
@@ -117,7 +117,7 @@ describe('Influx metrics', function () {
await clock.tickAsync(10)
expect(scope.isDone()).to.be.equal(
true,
`pending mocks: ${scope.pendingMocks()}`
`pending mocks: ${scope.pendingMocks()}`,
)
})
})
@@ -150,9 +150,9 @@ describe('Influx metrics', function () {
.and(
sinon.match.has(
'message',
'Cannot push metrics. Cause: RequestError: Nock: Disallowed net connect for "shields-metrics.io:443/metrics"'
)
)
'Cannot push metrics. Cause: RequestError: Nock: Disallowed net connect for "shields-metrics.io:443/metrics"',
),
),
)
})
@@ -167,9 +167,9 @@ describe('Influx metrics', function () {
.and(
sinon.match.has(
'message',
'Cannot push metrics. https://shields-metrics.io/metrics responded with status code 400'
)
)
'Cannot push metrics. https://shields-metrics.io/metrics responded with status code 400',
),
),
)
})
})

View File

@@ -4,7 +4,7 @@ function promClientJsonToInfluxV2(metrics, extraLabels = {}) {
return metrics
.flatMap(metric => {
const valuesByLabels = groupBy(metric.values, value =>
JSON.stringify(Object.entries(value.labels).sort())
JSON.stringify(Object.entries(value.labels).sort()),
)
return Object.values(valuesByLabels).map(metricsWithSameLabel => {
const labels = Object.entries(metricsWithSameLabel[0].labels)

View File

@@ -95,7 +95,7 @@ describe('Metric format converters', function () {
prometheus,le=50 histogram1_bucket=2
prometheus,le=15 histogram1_bucket=2
prometheus,le=5 histogram1_bucket=1
prometheus histogram1_count=3,histogram1_sum=111`)
prometheus histogram1_count=3,histogram1_sum=111`),
)
})
@@ -118,7 +118,7 @@ prometheus histogram1_count=3,histogram1_sum=111`)
prometheus,le=50 histogram1_bucket=2
prometheus,le=15 histogram1_bucket=2
prometheus,le=5 histogram1_bucket=1
prometheus histogram1_count=3,histogram1_sum=111`)
prometheus histogram1_count=3,histogram1_sum=111`),
)
})
@@ -145,7 +145,7 @@ prometheus histogram1_count=3,histogram1_sum=111`)
sortLines(`prometheus,quantile=0.99 summary1=100
prometheus,quantile=0.9 summary1=100
prometheus,quantile=0.1 summary1=1
prometheus summary1_count=3,summary1_sum=111`)
prometheus summary1_count=3,summary1_sum=111`),
)
})
@@ -167,7 +167,7 @@ prometheus summary1_count=3,summary1_sum=111`)
sortLines(`prometheus,quantile=0.99 summary1=100
prometheus,quantile=0.9 summary1=100
prometheus,quantile=0.1 summary1=1
prometheus summary1_count=3,summary1_sum=111`)
prometheus summary1_count=3,summary1_sum=111`),
)
})
@@ -204,7 +204,7 @@ prometheus summary1_count=3,summary1_sum=111`)
})
expect(influx).to.be.equal(
'prometheus,env=production,instance=instance1 counter1=11'
'prometheus,env=production,instance=instance1 counter1=11',
)
})
})

View File

@@ -79,7 +79,7 @@ export default class PrometheusMetrics {
return this.counters.serviceResponseSize.labels(
category,
serviceFamily,
service
service,
)
}
}

View File

@@ -65,11 +65,11 @@ const publicConfigSchema = Joi.object({
bind: {
port: Joi.alternatives().try(
Joi.number().port(),
Joi.string().pattern(/^\\\\\.\\pipe\\.+$/)
Joi.string().pattern(/^\\\\\.\\pipe\\.+$/),
),
address: Joi.alternatives().try(
Joi.string().ip().required(),
Joi.string().hostname().required()
Joi.string().hostname().required(),
),
},
metrics: {
@@ -154,8 +154,8 @@ const publicConfigSchema = Joi.object({
path.dirname(fileURLToPath(import.meta.url)),
'..',
'..',
'public'
)
'public',
),
),
requireCloudflare: Joi.boolean().required(),
}).required()
@@ -236,7 +236,7 @@ class Server {
const publicConfig = Joi.attempt(config.public, publicConfigSchema)
const privateConfig = this.validatePrivateConfig(
config.private,
privateConfigSchema
privateConfigSchema,
)
// We want to require an username and a password for the influx metrics
// only if the influx metrics are enabled. The private config schema
@@ -245,7 +245,7 @@ class Server {
if (publicConfig.metrics.influx && publicConfig.metrics.influx.enabled) {
this.validatePrivateConfig(
config.private,
privateMetricsInfluxConfigSchema
privateMetricsInfluxConfigSchema,
)
}
this.config = {
@@ -270,7 +270,7 @@ class Server {
Object.assign({}, publicConfig.metrics.influx, {
username: privateConfig.influx_username,
password: privateConfig.influx_password,
})
}),
)
}
}
@@ -283,8 +283,8 @@ class Server {
const badPaths = e.details.map(({ path }) => path)
throw Error(
`Private configuration is invalid. Check these paths: ${badPaths.join(
','
)}`
',',
)}`,
)
}
}
@@ -350,32 +350,35 @@ class Server {
makeSend(
'svg',
request.res,
end
end,
)(
makeBadge({
label: '410',
message: `${format} no longer available`,
color: 'lightgray',
format: 'svg',
})
}),
)
})
if (!rasterUrl) {
camp.route(/^\/((?!img\/)).*\.png$/, (query, match, end, request) => {
makeSend(
'svg',
request.res,
end
)(
makeBadge({
label: '404',
message: 'raster badges not available',
color: 'lightgray',
format: 'svg',
})
)
})
camp.route(
/^\/((?!img|assets\/)).*\.png$/,
(query, match, end, request) => {
makeSend(
'svg',
request.res,
end,
)(
makeBadge({
label: '404',
message: 'raster badges not available',
color: 'lightgray',
format: 'svg',
}),
)
},
)
}
camp.notfound(/(\.svg|\.json|)$/, (query, match, end, request) => {
@@ -385,14 +388,14 @@ class Server {
makeSend(
format,
request.res,
end
end,
)(
makeBadge({
label: '404',
message: 'badge not found',
color: 'red',
format,
})
}),
)
})
}
@@ -412,18 +415,21 @@ class Server {
if (rasterUrl) {
// Redirect to the raster server for raster versions of modern badges.
camp.route(/^\/((?!img\/)).*\.png$/, (queryParams, match, end, ask) => {
ask.res.statusCode = 301
ask.res.setHeader(
'Location',
rasterRedirectUrl({ rasterUrl }, ask.req.url)
)
camp.route(
/^\/((?!img|assets\/)).*\.png$/,
(queryParams, match, end, ask) => {
ask.res.statusCode = 301
ask.res.setHeader(
'Location',
rasterRedirectUrl({ rasterUrl }, ask.req.url),
)
const cacheDuration = (30 * 24 * 3600) | 0 // 30 days.
ask.res.setHeader('Cache-Control', `max-age=${cacheDuration}`)
const cacheDuration = (30 * 24 * 3600) | 0 // 30 days.
ask.res.setHeader('Cache-Control', `max-age=${cacheDuration}`)
ask.res.end()
})
ask.res.end()
},
)
}
if (redirectUrl) {
@@ -459,8 +465,8 @@ class Server {
rasterUrl: config.public.rasterUrl,
private: config.private,
public: config.public,
}
)
},
),
)
}

View File

@@ -19,7 +19,7 @@ describe('The server', function () {
public: {
documentRoot: path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
'test-public'
'test-public',
),
},
})
@@ -66,7 +66,7 @@ describe('The server', function () {
it('should return cors header for the request', async function () {
const { statusCode, headers } = await got(
`${baseUrl}badge/foo-bar-blue.svg`
`${baseUrl}badge/foo-bar-blue.svg`,
)
expect(statusCode).to.equal(200)
expect(headers['access-control-allow-origin']).to.equal('*')
@@ -77,11 +77,11 @@ describe('The server', function () {
`${baseUrl}:fruit-apple-green.png`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
expect(headers.location).to.equal(
'http://raster.example.test/:fruit-apple-green.png'
'http://raster.example.test/:fruit-apple-green.png',
)
})
@@ -90,11 +90,11 @@ describe('The server', function () {
`${baseUrl}badge/foo-bar-blue.png`,
{
followRedirect: false,
}
},
)
expect(statusCode).to.equal(301)
expect(headers.location).to.equal(
'http://raster.example.test/badge/foo-bar-blue.png'
'http://raster.example.test/badge/foo-bar-blue.png',
)
})
@@ -105,7 +105,7 @@ describe('The server', function () {
it('should produce SVG badges with expected headers', async function () {
const { statusCode, headers } = await got(
`${baseUrl}:fruit-apple-green.svg`
`${baseUrl}:fruit-apple-green.svg`,
)
expect(statusCode).to.equal(200)
expect(headers['content-type']).to.equal('image/svg+xml;charset=utf-8')
@@ -119,7 +119,7 @@ describe('The server', function () {
it('should produce JSON badges with expected headers', async function () {
const { statusCode, body, headers } = await got(
`${baseUrl}:fruit-apple-green.json`
`${baseUrl}:fruit-apple-green.json`,
)
expect(statusCode).to.equal(200)
expect(headers['content-type']).to.equal('application/json')
@@ -137,7 +137,7 @@ describe('The server', function () {
// https://github.com/badges/shields/pull/1319
it('should not crash with a numeric logo', async function () {
const { statusCode, body } = await got(
`${baseUrl}:fruit-apple-green.svg?logo=1`
`${baseUrl}:fruit-apple-green.svg?logo=1`,
)
expect(statusCode).to.equal(200)
expect(body)
@@ -148,7 +148,7 @@ describe('The server', function () {
it('should not crash with a numeric link', async function () {
const { statusCode, body } = await got(
`${baseUrl}:fruit-apple-green.svg?link=1`
`${baseUrl}:fruit-apple-green.svg?link=1`,
)
expect(statusCode).to.equal(200)
expect(body)
@@ -159,7 +159,7 @@ describe('The server', function () {
it('should not crash with a boolean link', async function () {
const { statusCode, body } = await got(
`${baseUrl}:fruit-apple-green.svg?link=true`
`${baseUrl}:fruit-apple-green.svg?link=true`,
)
expect(statusCode).to.equal(200)
expect(body)
@@ -173,7 +173,7 @@ describe('The server', function () {
`${baseUrl}this/is/not/a/badge.svg`,
{
throwHttpErrors: false,
}
},
)
expect(statusCode).to.equal(404)
expect(body)
@@ -187,7 +187,7 @@ describe('The server', function () {
`${baseUrl}this/is/most/definitely/not/a/badge.js`,
{
throwHttpErrors: false,
}
},
)
expect(statusCode).to.equal(404)
expect(body)
@@ -211,7 +211,7 @@ describe('The server', function () {
`${baseUrl}badge/foo-bar-blue.jpg`,
{
throwHttpErrors: false,
}
},
)
// TODO It would be nice if this were 404 or 410.
expect(statusCode).to.equal(200)
@@ -236,7 +236,7 @@ describe('The server', function () {
await server.start()
const { statusCode, body } = await got(
`${server.baseUrl}badge/foo-bar-blue.svg`
`${server.baseUrl}badge/foo-bar-blue.svg`,
)
expect(statusCode).to.be.equal(200)
@@ -365,7 +365,7 @@ describe('The server', function () {
it('should require url when influx configuration is enabled', function () {
delete customConfig.public.metrics.influx.url
expect(() => new Server(customConfig)).to.throw(
'"metrics.influx.url" is required'
'"metrics.influx.url" is required',
)
})
@@ -378,21 +378,21 @@ describe('The server', function () {
it('should require timeoutMilliseconds when influx configuration is enabled', function () {
delete customConfig.public.metrics.influx.timeoutMilliseconds
expect(() => new Server(customConfig)).to.throw(
'"metrics.influx.timeoutMilliseconds" is required'
'"metrics.influx.timeoutMilliseconds" is required',
)
})
it('should require intervalSeconds when influx configuration is enabled', function () {
delete customConfig.public.metrics.influx.intervalSeconds
expect(() => new Server(customConfig)).to.throw(
'"metrics.influx.intervalSeconds" is required'
'"metrics.influx.intervalSeconds" is required',
)
})
it('should require instanceIdFrom when influx configuration is enabled', function () {
delete customConfig.public.metrics.influx.instanceIdFrom
expect(() => new Server(customConfig)).to.throw(
'"metrics.influx.instanceIdFrom" is required'
'"metrics.influx.instanceIdFrom" is required',
)
})
@@ -400,7 +400,7 @@ describe('The server', function () {
customConfig.public.metrics.influx.instanceIdFrom = 'env-var'
delete customConfig.public.metrics.influx.instanceIdEnvVarName
expect(() => new Server(customConfig)).to.throw(
'"metrics.influx.instanceIdEnvVarName" is required'
'"metrics.influx.instanceIdEnvVarName" is required',
)
})
@@ -422,7 +422,7 @@ describe('The server', function () {
it('should require envLabel when influx configuration is enabled', function () {
delete customConfig.public.metrics.influx.envLabel
expect(() => new Server(customConfig)).to.throw(
'"metrics.influx.envLabel" is required'
'"metrics.influx.envLabel" is required',
)
})
@@ -439,14 +439,14 @@ describe('The server', function () {
it('should require username when influx configuration is enabled', function () {
delete customConfig.private.influx_username
expect(() => new Server(customConfig)).to.throw(
'Private configuration is invalid. Check these paths: influx_username'
'Private configuration is invalid. Check these paths: influx_username',
)
})
it('should require password when influx configuration is enabled', function () {
delete customConfig.private.influx_password
expect(() => new Server(customConfig)).to.throw(
'Private configuration is invalid. Check these paths: influx_password'
'Private configuration is invalid. Check these paths: influx_password',
)
})
@@ -505,7 +505,7 @@ describe('The server', function () {
})
.post(
'/metrics',
/prometheus,application=shields,category=static,env=localhost-env,family=static-badge,instance=test-instance,service=static_badge service_requests_total=1\n/
/prometheus,application=shields,category=static,env=localhost-env,family=static-badge,instance=test-instance,service=static_badge service_requests_total=1\n/,
)
.basicAuth({ user: 'influx-username', pass: 'influx-password' })
.reply(200)
@@ -515,7 +515,7 @@ describe('The server', function () {
expect(scope.isDone()).to.be.equal(
true,
`pending mocks: ${scope.pendingMocks()}`
`pending mocks: ${scope.pendingMocks()}`,
)
})
})

View File

@@ -121,8 +121,8 @@ if (typeof onlyServices === 'undefined' || onlyServices.includes('*****')) {
} else {
console.info(
`Running tests for ${onlyServices.length} services: ${onlyServices.join(
', '
)}.\n`
', ',
)}.\n`,
)
runner.only(onlyServices)
}

View File

@@ -23,7 +23,7 @@ async function createServiceTester() {
const ServiceClass = Object.values(await import(servicePath))[0]
if (!(ServiceClass.prototype instanceof BaseService)) {
throw Error(
`${servicePath} does not export a single service. Invoke new ServiceTester() directly.`
`${servicePath} does not export a single service. Invoke new ServiceTester() directly.`,
)
}
return ServiceTester.forServiceClass(ServiceClass)

View File

@@ -91,11 +91,11 @@ const factory = superclass =>
Joi.attempt(
json[name],
Joi.string().regex(expected),
`${name} mismatch:`
`${name} mismatch:`,
)
} else {
throw new Error(
"'expected' must be a string, a number, a regex, an array or a Joi schema"
"'expected' must be a string, a number, a regex, an array or a Joi schema",
)
}
}

View File

@@ -25,7 +25,7 @@ class Runner {
*/
async prepare() {
this.testers = (await loadTesters()).flatMap(testerModule =>
Object.values(testerModule)
Object.values(testerModule),
)
this.testers.forEach(tester => {
tester.beforeEach = () => {

View File

@@ -10,7 +10,7 @@ describe('Services from PR title', function () {
])
given('[CRAN CPAN CTAN] Add test coverage').expect(['cran', 'cpan', 'ctan'])
given(
'[RFC] Add Joi-based request validation to BaseJsonService and rewrite [NPM] badges'
'[RFC] Add Joi-based request validation to BaseJsonService and rewrite [NPM] badges',
).expect(['npm'])
given('make changes to [CRAN] and [CPAN]').expect(['cran', 'cpan'])
given('[github appveyor ]').expect(['github', 'appveyor'])

View File

@@ -36,7 +36,7 @@ describe('SQL token persistence', function () {
beforeEach('Create temporary table', async function () {
await pool.query(
`CREATE TEMPORARY TABLE ${tableName} (LIKE github_user_tokens INCLUDING ALL);`
`CREATE TEMPORARY TABLE ${tableName} (LIKE github_user_tokens INCLUDING ALL);`,
)
})
afterEach('Drop temporary table', async function () {
@@ -57,7 +57,7 @@ describe('SQL token persistence', function () {
initialTokens.forEach(async token => {
await pool.query(
`INSERT INTO pg_temp.${tableName} (token) VALUES ($1::text);`,
[token]
[token],
)
})
})
@@ -77,7 +77,7 @@ describe('SQL token persistence', function () {
await persistence.noteTokenAdded(newToken)
const result = await pool.query(
`SELECT token FROM pg_temp.${tableName};`
`SELECT token FROM pg_temp.${tableName};`,
)
const savedTokens = result.rows.map(row => row.token)
expect(savedTokens.sort()).to.deep.equal(expected)
@@ -93,7 +93,7 @@ describe('SQL token persistence', function () {
await persistence.noteTokenRemoved(toRemove)
const result = await pool.query(
`SELECT token FROM pg_temp.${tableName};`
`SELECT token FROM pg_temp.${tableName};`,
)
const savedTokens = result.rows.map(row => row.token)
expect(savedTokens.sort()).to.deep.equal(expected)

View File

@@ -28,14 +28,14 @@ export default class SqlTokenPersistence {
async onTokenAdded(token) {
return await this.pool.query(
`INSERT INTO ${this.table} (token) VALUES ($1::text) ON CONFLICT (token) DO NOTHING;`,
[token]
[token],
)
}
async onTokenRemoved(token) {
return await this.pool.query(
`DELETE FROM ${this.table} WHERE token=$1::text;`,
[token]
[token],
)
}

View File

@@ -21,16 +21,16 @@ describe('The token pool', function () {
it('should yield the expected tokens', function () {
ids.forEach(id =>
times(batchSize, () => expect(tokenPool.next().id).to.equal(id))
times(batchSize, () => expect(tokenPool.next().id).to.equal(id)),
)
})
it('should repeat when reaching the end', function () {
ids.forEach(id =>
times(batchSize, () => expect(tokenPool.next().id).to.equal(id))
times(batchSize, () => expect(tokenPool.next().id).to.equal(id)),
)
ids.forEach(id =>
times(batchSize, () => expect(tokenPool.next().id).to.equal(id))
times(batchSize, () => expect(tokenPool.next().id).to.equal(id)),
)
})

View File

@@ -16,7 +16,7 @@ const { fileMatch } = danger.git
const documentation = fileMatch(
'**/*.md',
'frontend/docs/**',
'frontend/src/**'
'frontend/src/**',
)
const server = fileMatch('core/server/**.js', '!*.spec.js')
const serverTests = fileMatch('core/server/**.spec.js')
@@ -33,7 +33,7 @@ message(
[
':sparkles: Thanks for your contribution to Shields, ',
`@${danger.github.pr.user.login}!`,
].join('')
].join(''),
)
const targetBranch = danger.github.pr.base.ref
@@ -48,7 +48,7 @@ if (documentation.edited) {
[
'Thanks for contributing to our documentation. ',
'We :heart: our [documentarians](http://www.writethedocs.org/)!',
].join('')
].join(''),
)
}
@@ -63,7 +63,7 @@ if (server.modified && !serverTests.modified) {
[
'This PR modified the server but none of its tests. <br>',
"That's okay so long as it's refactoring existing code.",
].join('')
].join(''),
)
}
@@ -74,7 +74,7 @@ if (legacyHelpers.created) {
[
'This PR modified helper functions in `lib/` but not accompanying tests. <br>',
"That's okay so long as it's refactoring existing code.",
].join('')
].join(''),
)
}
@@ -85,7 +85,7 @@ if (logos.created) {
'Please ensure your contribution follows our ',
'[guidance](https://github.com/badges/shields/blob/master/doc/logos.md#contributing-logos) ',
'for logo submissions.',
].join('')
].join(''),
)
}
@@ -94,7 +94,7 @@ if (capitals.created || underscores.created) {
[
'JavaScript source files should be named with `kebab-case` ',
'(dash-separated lowercase).',
].join('')
].join(''),
)
}
@@ -116,7 +116,7 @@ if (allFiles.length > 100) {
':books: Remember to ensure any changes to `config.private` ',
`in \`${file}\` are reflected in the [server secrets documentation]`,
'(https://github.com/badges/shields/blob/master/doc/server-secrets.md)',
].join('')
].join(''),
)
}
@@ -126,7 +126,7 @@ if (allFiles.length > 100) {
`Found 'assert' statement added in \`${file}\`. <br>`,
'Please ensure tests are written using Chai ',
'[expect syntax](http://chaijs.com/guide/styles/#expect)',
].join('')
].join(''),
)
}
@@ -135,7 +135,7 @@ if (allFiles.length > 100) {
[
`Found import of '@hapi/joi' in \`${file}\`. <br>`,
"Joi must be imported as 'joi'.",
].join('')
].join(''),
)
}
})
@@ -168,7 +168,7 @@ affectedServices.forEach(service => {
[
`This PR modified service code for <kbd>${service}</kbd> but not its test code. <br>`,
"That's okay so long as it's refactoring existing code.",
].join('')
].join(''),
)
}
})

View File

@@ -25,7 +25,7 @@ and learn about the [GitHub workflow](http://try.github.io/).
#### Node, NPM
Node >=16 and NPM >=8 is required. If you don't already have them,
Node >=16 and NPM 9.x is required. If you don't already have them,
install node and npm: https://nodejs.org/en/download/
### Setup a dev install

View File

@@ -1,38 +1,6 @@
# Logos
## Using Logos
### SimpleIcons
We support a wide range of logos via [SimpleIcons][]. They should be referenced by the logo slug e.g:
![](https://img.shields.io/npm/v/npm.svg?logo=nodedotjs) - https://img.shields.io/npm/v/npm.svg?logo=nodedotjs
The set of Simple Icon slugs can be found in the [slugs.md](https://github.com/simple-icons/simple-icons/blob/develop/slugs.md) file in the Simple Icons repository. NB - the Simple Icons site and that slugs.md page may at times contain new icons that haven't yet been pulled into the Shields.io runtime. More information on how and when we incorporate icon updates can be found [here](https://github.com/badges/shields/discussions/5369).
### Shields logos
We also maintain a small number of custom logos for some services: https://github.com/badges/shields/tree/master/logo They can also be referenced by name and take preference to SimpleIcons e.g:
![](https://img.shields.io/npm/v/npm.svg?logo=npm) - https://img.shields.io/npm/v/npm.svg?logo=npm
### Custom Logos
Any custom logo can be passed in a URL parameter by base64 encoding it. e.g:
![](https://img.shields.io/badge/play-station-blue.svg?logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEiIHdpZHRoPSI2MDAiIGhlaWdodD0iNjAwIj48cGF0aCBkPSJNMTI5IDExMWMtNTUgNC05MyA2Ni05MyA3OEwwIDM5OGMtMiA3MCAzNiA5MiA2OSA5MWgxYzc5IDAgODctNTcgMTMwLTEyOGgyMDFjNDMgNzEgNTAgMTI4IDEyOSAxMjhoMWMzMyAxIDcxLTIxIDY5LTkxbC0zNi0yMDljMC0xMi00MC03OC05OC03OGgtMTBjLTYzIDAtOTIgMzUtOTIgNDJIMjM2YzAtNy0yOS00Mi05Mi00MmgtMTV6IiBmaWxsPSIjZmZmIi8+PC9zdmc+) - https://img.shields.io/badge/play-station-blue.svg?logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEiIHdpZHRoPSI2MDAiIGhlaWdodD0iNjAwIj48cGF0aCBkPSJNMTI5IDExMWMtNTUgNC05MyA2Ni05MyA3OEwwIDM5OGMtMiA3MCAzNiA5MiA2OSA5MWgxYzc5IDAgODctNTcgMTMwLTEyOGgyMDFjNDMgNzEgNTAgMTI4IDEyOSAxMjhoMWMzMyAxIDcxLTIxIDY5LTkxbC0zNi0yMDljMC0xMi00MC03OC05OC03OGgtMTBjLTYzIDAtOTIgMzUtOTIgNDJIMjM2YzAtNy0yOS00Mi05Mi00MmgtMTV6IiBmaWxsPSIjZmZmIi8+PC9zdmc+
### logoColor parameter
The `logoColor` param can be used to set the color of the logo. Hex, rgb, rgba, hsl, hsla and css named colors can all be used. For SimpleIcons named logos (which are monochrome), the color will be applied to the SimpleIcons logo.
- ![](https://img.shields.io/badge/logo-javascript-blue?logo=javascript) - https://img.shields.io/badge/logo-javascript-blue?logo=javascript
- ![](https://img.shields.io/badge/logo-javascript-blue?logo=javascript&logoColor=f5f5f5) - https://img.shields.io/badge/logo-javascript-blue?logo=javascript&logoColor=f5f5f5
In the case where Shields hosts a custom multi-colored logo, if the `logoColor` param is passed, the corresponding SimpleIcons logo will be substituted and colored.
- ![](https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab) - https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab
- ![](https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab&logoColor=white) - https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab&logoColor=white
For documentation on using logos, see https://shields.io/docs/logos
## Contributing Logos
@@ -69,7 +37,6 @@ If you are submitting a pull request for a custom logo, please:
We try to ensure our logos are compliant with brand guidelines. If one of our custom logos does not conform to the necessary brand guidelines, please open an issue on the [shields.io tracker](https://github.com/badges/shields/issues) and we'll work with you to resolve it. If a logo from the simple-icons set does not conform to the relevant brand guidelines, please open an issue on the [simple-icons tracker](https://github.com/simple-icons/simple-icons/issues) first.
[simpleicons]: https://simpleicons.org/
[simple-icons github]: https://github.com/simple-icons/simple-icons
[svgo]: https://github.com/svg/svgo
[svgomg]: https://jakearchibald.github.io/svgomg/

View File

@@ -186,7 +186,7 @@ t.create('Build status (private application)')
.intercept(nock =>
nock('https://app.wercker.com/api/v3/applications/')
.get('/wercker/go-wercker-api/builds?limit=1')
.reply(401)
.reply(401),
)
.expectBadge({ label: 'build', message: 'private application not supported' })
```
@@ -227,7 +227,7 @@ t.create('Build passed')
.intercept(nock =>
nock('https://app.wercker.com/api/v3/applications/')
.get('/wercker/go-wercker-api/builds?limit=1')
.reply(200, [{ status: 'finished', result: 'passed' }])
.reply(200, [{ status: 'finished', result: 'passed' }]),
)
.expectBadge({
label: 'build',
@@ -240,7 +240,7 @@ t.create('Build failed')
.intercept(nock =>
nock('https://app.wercker.com/api/v3/applications/')
.get('/wercker/go-wercker-api/builds?limit=1')
.reply(200, [{ status: 'finished', result: 'failed' }])
.reply(200, [{ status: 'finished', result: 'failed' }]),
)
.expectBadge({ label: 'build', message: 'failed', color: 'red' })
```

View File

@@ -1,12 +1 @@
# Static Badges
It is possible to use shields.io to make a wide variety of badges displaying static text and/or logos. For example:
- ![any text you like](https://img.shields.io/badge/any%20text-you%20like-blue) - https://img.shields.io/badge/any%20text-you%20like-blue
- ![just the message](https://img.shields.io/badge/just%20the%20message-8A2BE2) - https://img.shields.io/badge/just%20the%20message-8A2BE2
- !['for the badge' style](https://img.shields.io/badge/%27for%20the%20badge%27%20style-20B2AA?style=for-the-badge) - https://img.shields.io/badge/%27for%20the%20badge%27%20style-20B2AA?style=for-the-badge
- ![with a logo](https://img.shields.io/badge/with%20a%20logo-grey?style=for-the-badge&logo=javascript) - https://img.shields.io/badge/with%20a%20logo-grey?style=for-the-badge&logo=javascript
Full documentation of styles and parameters: https://shields.io/#styles
More documentation on logos: https://github.com/badges/shields/blob/master/doc/logos.md
This documentation has moved to https://shields.io/docs/static-badges

View File

@@ -18,7 +18,7 @@ after('shut down the server', async function () {
it('should render a badge', async function () {
this.timeout('30s')
const { statusCode, body } = await got(
'http://localhost:1111/badge/fruit-apple-green.svg'
'http://localhost:1111/badge/fruit-apple-green.svg',
)
expect(statusCode).to.equal(200)
expect(body).to.satisfy(isSvg).and.to.include('fruit').and.to.include('apple')

View File

@@ -0,0 +1,21 @@
---
slug: new-frontend
title: We launched a new frontend
authors:
name: chris48s
title: Shields.io Core Team
url: https://github.com/chris48s
image_url: https://avatars.githubusercontent.com/u/6025893
tags: []
---
Alongside the general visual refresh and improvements to look and feel, our new frontend has allowed us to address a number of long-standing feature requests and enhancements:
- Clearer and more discoverable documentation for our [static](https://shields.io/badges/static-badge), dynamic [json](https://shields.io/badges/dynamic-json-badge)/[xml](https://shields.io/badges/dynamic-xml-badge)/[yaml](https://shields.io/badges/dynamic-yaml-badge) and [endpoint](https://shields.io/badges/endpoint-badge) badges
- Improved badge builder interface, with all optional query parameters included in the builder for each badge
- Each badge now has its own documentation page, which we can link to. e.g: [https://shields.io/badges/discord](https://shields.io/badges/discord)
- Light/dark mode themes
- Improved search
- Documentation for individual path and query parameters
The new site also comes with big maintenance benefits for the core team. We rely heavily on [docusaurus](https://docusaurus.io/), [docusaurus-openapi](https://github.com/cloud-annotations/docusaurus-openapi), and [docusaurus-search-local](https://github.com/easyops-cn/docusaurus-search-local). This moves us to a mostly declarative setup, massively reducing the amount of custom frontend code we maintain ourselves.

View File

@@ -0,0 +1,19 @@
---
slug: tag-filter
title: Applying filters to GitHub Tag and Release badges
authors:
name: chris48s
title: Shields.io Core Team
url: https://github.com/chris48s
image_url: https://avatars.githubusercontent.com/u/6025893
tags: []
---
We recently shipped a feature which allows you to pass an arbitrary filter to the GitHub tag and release badges. The `filter` param can be used to apply a filter to the project's tag or release names before selecting the latest from the list. Two constructs are available: `*` is a wildcard matching zero or more characters, and if the pattern starts with a `!`, the whole pattern is negated.
To give an example of how this might be useful, we create two types of tags on our GitHub repo: https://github.com/badges/shields/tags There are tags in the format `major.minor.patch` which correspond to our [NPM package releases](https://www.npmjs.com/package/badge-maker?activeTab=versions) and tags in the format `server-YYYY-MM-DD` that correspond to our [docker snapshot releases](https://registry.hub.docker.com/r/shieldsio/shields/tags?page=1&ordering=last_updated).
In our case, this would allow us to make a badge that applies the filter `!server-*` to filter out the snapshot tags and just select the latest package tag.
- ![tag badge without filter](https://img.shields.io/github/v/tag/badges/shields) - https://img.shields.io/github/v/tag/badges/shields
- ![tag badge with filter](https://img.shields.io/github/v/tag/badges/shields?filter=%21server-%2A) - https://img.shields.io/github/v/tag/badges/shields?filter=%21server-%2A

13
frontend/docs/index.md Normal file
View File

@@ -0,0 +1,13 @@
---
sidebar_position: 1
---
# Intro
Shields.io is a service for concise, consistent, and legible badges, which can easily be included in GitHub readmes or any other web page. The service supports dozens of continuous integration services, package registries, distributions, app stores, social networks, code coverage services, and code analysis services. It is used by some of the world's most popular open-source projects.
Browse a [complete list of badges](/badges) and locate a particular badge by using the search bar or by browsing the categories.
Use the builder to fill in required path parameters for that badge type (like your username or repo) and optionally customize (label, colors etc.). And it's ready for use! Copy your badge url or code snippet, which can then be added to places like your GitHub readme files or other web pages.
![screenshot of the badge builder](/img/builder.png)

View File

@@ -1,5 +0,0 @@
---
sidebar_position: 1
---
# TODO

37
frontend/docs/logos.md Normal file
View File

@@ -0,0 +1,37 @@
---
sidebar_position: 2
---
# Logos
## SimpleIcons
We support a wide range of logos via [SimpleIcons](https://simpleicons.org/). All simple-icons are referenced using icon slugs. e.g:
![](https://img.shields.io/npm/v/npm.svg?logo=nodedotjs) - https://img.shields.io/npm/v/npm.svg?logo=nodedotjs
You can click the icon title on <a href="https://simpleicons.org/" rel="noopener noreferrer" target="_blank">simple-icons</a> to copy the slug or they can be found in the <a href="https://github.com/simple-icons/simple-icons/blob/master/slugs.md">slugs.md file</a> in the simple-icons repository. NB - the Simple Icons site and slugs.md page may at times contain new icons that haven't yet been pulled into Shields.io yet. More information on how and when we incorporate icon updates can be found [here](https://github.com/badges/shields/discussions/5369).
## Shields logos
We also maintain a small number of custom logos for a handful of services: https://github.com/badges/shields/tree/master/logo They can also be referenced by name and take preference to SimpleIcons e.g:
![](https://img.shields.io/npm/v/npm.svg?logo=npm) - https://img.shields.io/npm/v/npm.svg?logo=npm
## Custom Logos
Any custom logo can be passed in a URL parameter by base64 encoding it. e.g:
![](https://img.shields.io/badge/play-station-blue.svg?logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEiIHdpZHRoPSI2MDAiIGhlaWdodD0iNjAwIj48cGF0aCBkPSJNMTI5IDExMWMtNTUgNC05MyA2Ni05MyA3OEwwIDM5OGMtMiA3MCAzNiA5MiA2OSA5MWgxYzc5IDAgODctNTcgMTMwLTEyOGgyMDFjNDMgNzEgNTAgMTI4IDEyOSAxMjhoMWMzMyAxIDcxLTIxIDY5LTkxbC0zNi0yMDljMC0xMi00MC03OC05OC03OGgtMTBjLTYzIDAtOTIgMzUtOTIgNDJIMjM2YzAtNy0yOS00Mi05Mi00MmgtMTV6IiBmaWxsPSIjZmZmIi8+PC9zdmc+) - https://img.shields.io/badge/play-station-blue.svg?logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEiIHdpZHRoPSI2MDAiIGhlaWdodD0iNjAwIj48cGF0aCBkPSJNMTI5IDExMWMtNTUgNC05MyA2Ni05MyA3OEwwIDM5OGMtMiA3MCAzNiA5MiA2OSA5MWgxYzc5IDAgODctNTcgMTMwLTEyOGgyMDFjNDMgNzEgNTAgMTI4IDEyOSAxMjhoMWMzMyAxIDcxLTIxIDY5LTkxbC0zNi0yMDljMC0xMi00MC03OC05OC03OGgtMTBjLTYzIDAtOTIgMzUtOTIgNDJIMjM2YzAtNy0yOS00Mi05Mi00MmgtMTV6IiBmaWxsPSIjZmZmIi8+PC9zdmc+
## logoColor parameter
The `logoColor` param can be used to set the color of the logo. Hex, rgb, rgba, hsl, hsla and css named colors can all be used. For SimpleIcons named logos (which are monochrome), the color will be applied to the SimpleIcons logo.
- ![](https://img.shields.io/badge/logo-javascript-blue?logo=javascript) - https://img.shields.io/badge/logo-javascript-blue?logo=javascript
- ![](https://img.shields.io/badge/logo-javascript-blue?logo=javascript&logoColor=f5f5f5) - https://img.shields.io/badge/logo-javascript-blue?logo=javascript&logoColor=f5f5f5
In the case where Shields hosts a custom multi-colored logo, if the `logoColor` param is passed, the corresponding SimpleIcons logo will be substituted and colored.
- ![](https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab) - https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab
- ![](https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab&logoColor=white) - https://img.shields.io/badge/logo-gitlab-blue?logo=gitlab&logoColor=white

View File

@@ -0,0 +1,13 @@
# Static Badges
It is possible to use shields.io to make a wide variety of badges displaying static text and/or logos. For example:
- ![any text you like](https://img.shields.io/badge/any%20text-you%20like-blue) - https://img.shields.io/badge/any%20text-you%20like-blue
- ![just the message](https://img.shields.io/badge/just%20the%20message-8A2BE2) - https://img.shields.io/badge/just%20the%20message-8A2BE2
- !['for the badge' style](https://img.shields.io/badge/%27for%20the%20badge%27%20style-20B2AA?style=for-the-badge) - https://img.shields.io/badge/%27for%20the%20badge%27%20style-20B2AA?style=for-the-badge
- ![with a logo](https://img.shields.io/badge/with%20a%20logo-grey?style=for-the-badge&logo=javascript) - https://img.shields.io/badge/with%20a%20logo-grey?style=for-the-badge&logo=javascript
For more info, see:
- [Static badge builder](/badges/static-badge), including full documentation of styles and parameters
- [Logos](/docs/logos)

View File

@@ -1,5 +1,5 @@
const lightCodeTheme = require('prism-react-renderer/themes/github')
const darkCodeTheme = require('prism-react-renderer/themes/dracula')
const lightCodeTheme = require('prism-react-renderer').themes.github
const darkCodeTheme = require('prism-react-renderer').themes.dracula
/** @type {import('@docusaurus/types').Config} */
const config = {
@@ -31,11 +31,11 @@ const config = {
({
docs: {
sidebarPath: require.resolve('./sidebars.cjs'),
editUrl: 'https://github.com/badges/shields/',
editUrl: 'https://github.com/badges/shields/tree/master/frontend',
},
blog: {
showReadingTime: true,
editUrl: 'https://github.com/badges/shields/',
editUrl: 'https://github.com/badges/shields/tree/master/frontend',
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
@@ -60,7 +60,13 @@ const config = {
},
items: [
{ to: '/badges', label: 'Badges', position: 'left' },
{
to: '/docs',
label: 'Documentation',
position: 'left',
},
{ to: '/community', label: 'Community', position: 'left' },
{ to: '/blog', label: 'Blog', position: 'left' },
{
href: 'https://github.com/badges/shields',
label: 'GitHub',

View File

@@ -35,7 +35,13 @@ const FeatureList = [
description: (
<>
Render badges in your own application using our{' '}
<a href="https://www.npmjs.com/package/badge-maker">NPM library</a>
<a
href="https://www.npmjs.com/package/badge-maker"
rel="noreferrer"
target="_blank"
>
NPM library
</a>
<br />
<code>npm install badge-maker</code>
</>
@@ -46,7 +52,11 @@ const FeatureList = [
description: (
<>
Host a shields instance behind your firewall with our{' '}
<a href="https://registry.hub.docker.com/r/shieldsio/shields/">
<a
href="https://registry.hub.docker.com/r/shieldsio/shields/"
rel="noreferrer"
target="_blank"
>
docker image
</a>
<br />
@@ -59,8 +69,14 @@ const FeatureList = [
description: (
<>
Please consider{' '}
<a href="https://opencollective.com/shields">donating</a> to sustain our
activities
<a
href="https://opencollective.com/shields"
rel="noreferrer"
target="_blank"
>
donating
</a>{' '}
to sustain our activities
</>
),
},

View File

@@ -26,3 +26,27 @@
html[data-theme="dark"] .docusaurus-highlight-code-line {
background-color: rgba(0, 0, 0, 0.3);
}
.opencollective-image {
color-scheme: initial;
}
/*
TODO: remove these three styles when
we can upgrade to docusaurus-theme-openapi@0.6.5
*/
input[type="text"], :not(#fakeID#fakeId#fakeID) select {
border-color: var(--ifm-color-primary-lightest);
border-style: solid;
border-width: 1px;
}
div.api-code-tab-group {
justify-content: center;
flex-wrap: wrap;
}
div.api-code-tab-group button.api-code-tab {
width: unset;
}

View File

@@ -22,7 +22,10 @@ Shields.io is possible thanks to the people and companies who donate money, serv
💵 These organisations help keep shields running by donating on OpenCollective. Your organisation can support this project by <a href="https://opencollective.com/shields#sponsor">becoming a sponsor </a>. Your logo will show up here with a link to your website.
<p>
<object data="https://opencollective.com/shields/sponsors.svg?avatarHeight=80&width=600" />
<object
data="https://opencollective.com/shields/sponsors.svg?avatarHeight=80&width=600"
class="opencollective-image"
></object>
</p>
## Backers
@@ -30,7 +33,10 @@ Shields.io is possible thanks to the people and companies who donate money, serv
💵 Thank you to all our backers who help keep shields running by donating on OpenCollective. You can support this project by <a href="https://opencollective.com/shields#backer">becoming a backer</a>.
<p>
<object data="https://opencollective.com/shields/backers.svg?width=600" />
<object
data="https://opencollective.com/shields/backers.svg?width=600"
class="opencollective-image">
</object>
</p>
## Contributors
@@ -38,7 +44,10 @@ Shields.io is possible thanks to the people and companies who donate money, serv
🙏 This project exists thanks to all the nice people who contribute their time to work on the project.
<p>
<object data="https://opencollective.com/shields/contributors.svg?width=600" />
<object
data="https://opencollective.com/shields/contributors.svg?width=600"
class="opencollective-image"
></object>
</p>
✨ Shields is helped by these companies which provide a free plan for their product or service:

View File

@@ -27,8 +27,8 @@ export default function Home() {
const { siteConfig } = useDocusaurusContext()
return (
<Layout
description="Description will go into a meta tag in <head />"
title={`${siteConfig.title}`}
description="Concise, consistent, and legible badges"
title={siteConfig.title}
>
<HomepageHeader />
<main>

View File

@@ -2,7 +2,7 @@ import React, { useRef, useState, useEffect } from 'react'
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'
import clsx from 'clsx'
import codegen from 'postman-code-generators'
import Highlight, { defaultProps } from 'prism-react-renderer'
import { Highlight } from 'prism-react-renderer'
import { useTypedSelector } from '@theme/ApiDemoPanel/hooks'
import buildPostmanRequest from '@theme/ApiDemoPanel/buildPostmanRequest'
import FloatingButton from '@theme/ApiDemoPanel/FloatingButton'
@@ -183,11 +183,11 @@ function Curl({ postman, codeSamples }) {
}
setCodeText(snippet)
}
},
)
} else if (language && !!language.source) {
setCodeText(
language.source.replace('$url', postmanRequest.url.toString())
language.source.replace('$url', postmanRequest.url.toString()),
)
} else {
setCodeText('')
@@ -230,7 +230,7 @@ function Curl({ postman, codeSamples }) {
className={clsx(
language === lang ? styles.selected : undefined,
language === lang ? 'api-code-tab--active' : undefined,
'api-code-tab'
'api-code-tab',
)}
key={lang.tabName || lang.label}
onClick={() => setLanguage(lang)}
@@ -241,7 +241,6 @@ function Curl({ postman, codeSamples }) {
</div>
<Highlight
{...defaultProps}
code={codeText}
language={language.highlight || language.lang}
theme={languageTheme}

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -9,7 +9,7 @@ function loadLogos() {
const logoDir = path.join(
path.dirname(fileURLToPath(import.meta.url)),
'..',
'logo'
'logo',
)
const logoFiles = fs.readdirSync(logoDir)
logoFiles.forEach(filename => {

Some files were not shown because too many files have changed in this diff Show More