Merge pull request #106 from thornbill/test-doc-urls

This commit is contained in:
Bill Thornton 2022-08-25 14:43:27 -04:00 committed by GitHub
commit 784e833720
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 401 additions and 18 deletions

40
.github/workflows/test.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: test
on:
pull_request:
branches: [master]
push:
branches: [master]
jobs:
test-urls:
name: Test URLs
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
command:
- test:blog-urls
- test:docs-urls
- test:web-urls
steps:
- name: Check out Git repository
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2
- name: Set up Node.js
uses: actions/setup-node@2fddd8803e2f5c9604345a0b591c3020ee971a93 # tag=v3.4.1
with:
node-version: 16
check-latest: true
cache: npm
- name: Build and start test server
run: |
npm ci --no-audit
npm run build
npm run serve &
- name: Test URL
run: npm run ${{ matrix.command }}

View File

@ -115,7 +115,13 @@ module.exports = {
[
'@docusaurus/plugin-client-redirects',
{
fromExtensions: ['html']
fromExtensions: ['html'],
redirects: [
{
from: ['/categories', '/tags'],
to: '/posts'
}
]
}
]
]

173
package-lock.json generated
View File

@ -39,6 +39,7 @@
"eslint-plugin-promise": "6.0.0",
"eslint-plugin-react": "7.30.1",
"eslint-plugin-react-hooks": "4.6.0",
"node-fetch": "^3.2.10",
"prettier": "2.7.1",
"typescript": "4.7.4",
"typescript-plugin-css-modules": "3.4.0"
@ -9527,6 +9528,25 @@
"node-fetch": "2.6.7"
}
},
"node_modules/cross-fetch/node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -9881,6 +9901,15 @@
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
"dev": true
},
"node_modules/data-uri-to-buffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz",
"integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==",
"dev": true,
"engines": {
"node": ">= 12"
}
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -12093,6 +12122,29 @@
"node": ">=0.4.0"
}
},
"node_modules/fetch-blob": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "paypal",
"url": "https://paypal.me/jimmywarting"
}
],
"dependencies": {
"node-domexception": "^1.0.0",
"web-streams-polyfill": "^3.0.3"
},
"engines": {
"node": "^12.20 || >= 14.13"
}
},
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -12343,6 +12395,18 @@
"node": ">=6"
}
},
"node_modules/formdata-polyfill": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
"dev": true,
"dependencies": {
"fetch-blob": "^3.1.2"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@ -14741,6 +14805,25 @@
"tslib": "^2.0.3"
}
},
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "github",
"url": "https://paypal.me/jimmywarting"
}
],
"engines": {
"node": ">=10.5.0"
}
},
"node_modules/node-emoji": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
@ -14750,22 +14833,21 @@
}
},
"node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"version": "3.2.10",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.10.tgz",
"integrity": "sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==",
"dev": true,
"dependencies": {
"whatwg-url": "^5.0.0"
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
},
"engines": {
"node": "4.x || >=6.0.0"
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/node-fetch"
}
},
"node_modules/node-forge": {
@ -19930,6 +20012,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/web-streams-polyfill": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
@ -27570,6 +27661,16 @@
"integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
"requires": {
"node-fetch": "2.6.7"
},
"dependencies": {
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"requires": {
"whatwg-url": "^5.0.0"
}
}
}
},
"cross-spawn": {
@ -27819,6 +27920,12 @@
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
"dev": true
},
"data-uri-to-buffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz",
"integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==",
"dev": true
},
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -29446,6 +29553,16 @@
"xml-js": "^1.6.11"
}
},
"fetch-blob": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
"dev": true,
"requires": {
"node-domexception": "^1.0.0",
"web-streams-polyfill": "^3.0.3"
}
},
"file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -29615,6 +29732,15 @@
}
}
},
"formdata-polyfill": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
"dev": true,
"requires": {
"fetch-blob": "^3.1.2"
}
},
"forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@ -31345,6 +31471,12 @@
"tslib": "^2.0.3"
}
},
"node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
"dev": true
},
"node-emoji": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
@ -31354,11 +31486,14 @@
}
},
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"version": "3.2.10",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.2.10.tgz",
"integrity": "sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==",
"dev": true,
"requires": {
"whatwg-url": "^5.0.0"
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
}
},
"node-forge": {
@ -35048,6 +35183,12 @@
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz",
"integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw=="
},
"web-streams-polyfill": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
"dev": true
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",

View File

@ -15,7 +15,10 @@
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"lint": "eslint --ext .ts,.js,.json,.jsx,.tsx ."
"lint": "eslint --ext .ts,.js,.json,.jsx,.tsx .",
"test:blog-urls": "node ./scripts/check-urls.mjs ./scripts/data/jellyfin-blog-urls.json",
"test:docs-urls": "node ./scripts/check-urls.mjs ./scripts/data/jellyfin-docs-urls.json",
"test:web-urls": "node ./scripts/check-urls.mjs ./scripts/data/jellyfin-web-urls.json"
},
"dependencies": {
"@docusaurus/core": "2.0.1",
@ -61,6 +64,7 @@
"eslint-plugin-promise": "6.0.0",
"eslint-plugin-react": "7.30.1",
"eslint-plugin-react-hooks": "4.6.0",
"node-fetch": "^3.2.10",
"prettier": "2.7.1",
"typescript": "4.7.4",
"typescript-plugin-css-modules": "3.4.0"

68
scripts/check-urls.mjs Normal file
View File

@ -0,0 +1,68 @@
import fetch from 'node-fetch';
import * as fs from 'node:fs/promises';
import path from 'node:path';
// 1xx, 2xx, and 3xx http status do not indicate errors
const isErrorStatus = (status) => Math.floor(status / 100) > 3;
// HACK: URLs containing periods are not handled correctly by the docusaurus test server currently. The following URLs
// return 404s even though they exist and work as expected on GH Pages.
const isProblematicUrl = (url) =>
['/posts/roku-v1.5.0/', '/posts/android-v2.4.0/', '/posts/android-v2.3.0/', '/posts/android-v2.1.0/'].includes(url);
// A path parameter is required to provide a JSON file containing a list of URLs to check
const [, , pathArg] = process.argv;
if (!pathArg) {
throw new Error('path is required');
}
const filePath = path.resolve(process.cwd(), pathArg);
const urls = JSON.parse(await fs.readFile(filePath));
// The host to check can be overriden by an environment variable
const HOST = process.env.CHECK_URL_HOST || 'http://localhost:3000';
// List of any failed requests
const failures = [];
const warnings = [];
await Promise.allSettled(
urls.map(async (url) => {
console.log(`Checking URL >> ${HOST}${url}`);
try {
const response = await fetch(`${HOST}${url}`);
if (isErrorStatus(response.status)) {
if (response.status === 404 && isProblematicUrl(url)) {
warnings.push({ url, response });
} else {
failures.push({
url,
error: new Error(`HTTP Error: ${response.status} ${response.statusText}`),
response
});
}
}
} catch (error) {
failures.push({ url, error });
}
})
);
if (warnings.length > 0) {
console.warn(
[
'⚠ The following URLs returned 404s, but should have succeeded',
...warnings.map((warning) => `${HOST}${warning.url}`)
].join('\n')
);
}
if (failures.length > 0) {
console.error(['❌ The following URLs failed', ...failures.map((failure) => `${HOST}${failure.url}`)].join('\n'));
process.exit(1);
}
if (warnings.length === 0) {
console.log('🚀 All URLs successful');
}

View File

@ -0,0 +1,39 @@
[
"/",
"/posts/android-tv-14/",
"/posts/",
"/posts/roku-v1.5.0/",
"/posts/webos-july2022/",
"/posts/jellyfin-10-8-0/",
"/posts/ios-update-150/",
"/posts/android-tv-13/",
"/posts/android-v2.4.0/",
"/posts/android-tv-12/",
"/posts/android-v2.3.0/",
"/posts/android-betas/",
"/posts/client-jmp/",
"/posts/a-note-about-privacy-and-expo/",
"/posts/mirrorbits-cdn/",
"/posts/android-on-fdroid/",
"/posts/jellyfin-apt-key/",
"/posts/android-v2.1.0/",
"/posts/android-next/",
"/posts/client-videotape/",
"/posts/jellyfin-10-6-0/",
"/posts/plugin-updates/",
"/posts/packaging-updates/",
"/posts/client-infuse/",
"/posts/jellyfin-xbox/",
"/clients/",
"/posts/jellyfin-10-5-0/",
"/posts/kodi-0-5-0/",
"/posts/client-mpv/",
"/posts/android-tv-11/",
"/posts/jellyfin-in-2019/",
"/posts/welcome/",
"/contact/",
"/downloads/",
"/contribute/",
"/categories/",
"/tags/"
]

View File

@ -0,0 +1,63 @@
[
"/docs/general/about.html",
"/docs/general/administration/building.html",
"/docs/general/administration/configuration.html",
"/docs/general/administration/hardware-acceleration.html",
"/docs/general/administration/install/synology.html",
"/docs/general/administration/installing.html",
"/docs/general/administration/migrate.html",
"/docs/general/administration/troubleshooting.html",
"/docs/general/clients/codec-support.html",
"/docs/general/clients/css-customization.html",
"/docs/general/clients/index.html",
"/docs/general/clients/kodi.html",
"/docs/general/clients/mopidy.html",
"/docs/general/clients/web-config.html",
"/docs/general/community-standards.html",
"/docs/general/contributing/branding.html",
"/docs/general/contributing/development.html",
"/docs/general/contributing/index.html",
"/docs/general/contributing/issues.html",
"/docs/general/contributing/release-procedure.html",
"/docs/general/contributing/source-tree.html",
"/docs/general/faq.html",
"/docs/general/getting-help.html",
"/docs/general/networking/apache.html",
"/docs/general/networking/caddy.html",
"/docs/general/networking/dlna.html",
"/docs/general/networking/fail2ban.html",
"/docs/general/networking/haproxy.html",
"/docs/general/networking/index.html",
"/docs/general/networking/letsencrypt.html",
"/docs/general/networking/monitoring.html",
"/docs/general/networking/nginx.html",
"/docs/general/networking/traefik.html",
"/docs/general/networking/traefik2.html",
"/docs/general/quick-start.html",
"/docs/general/server/devices.html",
"/docs/general/server/libraries.html",
"/docs/general/server/live-tv/index.html",
"/docs/general/server/live-tv/post-process.html",
"/docs/general/server/live-tv/setup-guide.html",
"/docs/general/server/media/books.html",
"/docs/general/server/media/comics.html",
"/docs/general/server/media/external-files.html",
"/docs/general/server/media/internet-radio.html",
"/docs/general/server/media/movies.html",
"/docs/general/server/media/music.html",
"/docs/general/server/media/shows.html",
"/docs/general/server/notifications.html",
"/docs/general/server/plugins/index.html",
"/docs/general/server/plugins/open-subtitles.html",
"/docs/general/server/plugins/tvheadend.html",
"/docs/general/server/quick-connect.html",
"/docs/general/server/settings.html",
"/docs/general/server/storage.html",
"/docs/general/server/tasks.html",
"/docs/general/server/transcoding.html",
"/docs/general/server/users/adding-managing-users.html",
"/docs/general/server/users/index.html",
"/docs/general/style-guides/index.html",
"/docs/general/style-guides/javascript.html",
"/docs/index.html"
]

View File

@ -0,0 +1,22 @@
[
"/docs/general/administration/hardware-acceleration.html",
"/docs/general/contributing/index.html",
"/docs/general/networking/dlna.html",
"/docs/general/networking/index.html",
"/docs/general/quick-start.html",
"/docs/general/server/devices.html",
"/docs/general/server/libraries.html",
"/docs/general/server/live-tv/index.html",
"/docs/general/server/live-tv/setup-guide.html",
"/docs/general/server/media/books.html",
"/docs/general/server/media/external-files.html",
"/docs/general/server/media/movies.html",
"/docs/general/server/media/music.html",
"/docs/general/server/media/shows.html",
"/docs/general/server/notifications.html",
"/docs/general/server/plugins/index.html",
"/docs/general/server/settings.html",
"/docs/general/server/tasks.html",
"/docs/general/server/transcoding.html",
"/docs/general/server/users/adding-managing-users.html"
]