mirror of
https://github.com/veggiemonk/awesome-docker.git
synced 2026-03-09 07:25:57 -05:00
chore: remove Node.js tooling, update maintenance docs
Remove package.json, build.js, tests/*.mjs, .nvmrc, and the old website template. Update MAINTENANCE.md with Go CLI commands. Switch dependabot from npm to gomod. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
31
.github/MAINTENANCE.md
vendored
31
.github/MAINTENANCE.md
vendored
@@ -30,7 +30,7 @@ This guide helps maintainers keep the awesome-docker list up-to-date and high-qu
|
||||
4. Remove projects that are truly abandoned/broken
|
||||
|
||||
### Quarterly Deep Dive (Every 3 months)
|
||||
1. Run: `npm run health-check` for detailed report
|
||||
1. Run: `./awesome-docker health` then `./awesome-docker report` for detailed report
|
||||
2. Review project categories - are they still relevant?
|
||||
3. Check for popular new Docker tools to add
|
||||
4. Update documentation links if newer versions exist
|
||||
@@ -39,25 +39,34 @@ This guide helps maintainers keep the awesome-docker list up-to-date and high-qu
|
||||
1. Remove all `:skull:` projects older than 1 year
|
||||
2. Review CONTRIBUTING.md guidelines
|
||||
3. Update year references in documentation
|
||||
4. Check Node.js version requirements
|
||||
|
||||
## 🛠️ Maintenance Commands
|
||||
|
||||
```bash
|
||||
# Test all links (requires GITHUB_TOKEN)
|
||||
npm test
|
||||
# Build the CLI
|
||||
go build -o awesome-docker ./cmd/awesome-docker
|
||||
|
||||
# Test PR changes only
|
||||
npm run test-pr
|
||||
# Lint README formatting (add --fix to auto-fix)
|
||||
./awesome-docker lint
|
||||
./awesome-docker lint --fix
|
||||
|
||||
# Generate health report (requires GITHUB_TOKEN)
|
||||
npm run health-check
|
||||
# Check all links (requires GITHUB_TOKEN for GitHub repos)
|
||||
./awesome-docker check
|
||||
|
||||
# PR validation (lint + external link check)
|
||||
./awesome-docker validate
|
||||
|
||||
# Score repository health (requires GITHUB_TOKEN)
|
||||
./awesome-docker health
|
||||
|
||||
# Generate health report from cache
|
||||
./awesome-docker report
|
||||
|
||||
# Build the website
|
||||
npm run build
|
||||
./awesome-docker build
|
||||
|
||||
# Update dependencies
|
||||
npm update
|
||||
# Run tests
|
||||
go test ./...
|
||||
```
|
||||
|
||||
## 📊 Quality Standards
|
||||
|
||||
8
.github/dependabot.yml
vendored
8
.github/dependabot.yml
vendored
@@ -1,17 +1,13 @@
|
||||
version: 2
|
||||
updates:
|
||||
# Enable version updates for npm
|
||||
- package-ecosystem: "npm"
|
||||
# Look for `package.json` and `lock` files in the `root` directory
|
||||
# Enable version updates for Go modules
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
# Check the npm registry for updates every day (weekdays)
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
# Enable version updates for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
# Workflow files stored in the default location of `.github/workflows`
|
||||
# You don't need to specify `/.github/workflows` for `directory`. You can use `directory: "/"`.
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
51
build.js
51
build.js
@@ -1,51 +0,0 @@
|
||||
const fs = require('fs-extra');
|
||||
const cheerio = require('cheerio');
|
||||
const showdown = require('showdown');
|
||||
|
||||
process.env.NODE_ENV = 'production';
|
||||
|
||||
const LOG = {
|
||||
error: (...args) => console.error('❌ ERROR', { ...args }),
|
||||
debug: (...args) => {
|
||||
if (process.env.DEBUG) console.log('💡 DEBUG: ', { ...args });
|
||||
},
|
||||
};
|
||||
const handleFailure = (err) => {
|
||||
LOG.error(err);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
process.on('unhandledRejection', handleFailure);
|
||||
|
||||
// --- FILES
|
||||
const README = 'README.md';
|
||||
const WEBSITE_FOLDER = 'website';
|
||||
const indexTemplate = `${WEBSITE_FOLDER}/index.tmpl.html`;
|
||||
const indexDestination = `${WEBSITE_FOLDER}/index.html`;
|
||||
|
||||
async function processIndex() {
|
||||
const converter = new showdown.Converter();
|
||||
converter.setFlavor('github');
|
||||
|
||||
try {
|
||||
LOG.debug('Loading files...', { indexTemplate, README });
|
||||
const template = await fs.readFile(indexTemplate, 'utf8');
|
||||
const markdown = await fs.readFile(README, 'utf8');
|
||||
|
||||
LOG.debug('Merging files...');
|
||||
const $ = cheerio.load(template);
|
||||
$('#md').append(converter.makeHtml(markdown));
|
||||
|
||||
LOG.debug('Writing index.html');
|
||||
await fs.outputFile(indexDestination, $.html(), 'utf8');
|
||||
LOG.debug('DONE 👍');
|
||||
} catch (err) {
|
||||
handleFailure(err);
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await processIndex();
|
||||
}
|
||||
|
||||
main();
|
||||
619
package-lock.json
generated
619
package-lock.json
generated
@@ -1,619 +0,0 @@
|
||||
{
|
||||
"name": "awesome-docker-website",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "awesome-docker-website",
|
||||
"version": "1.0.0",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"cheerio": "1.2.0",
|
||||
"draftlog": "1.0.13",
|
||||
"fs-extra": "11.3.3",
|
||||
"node-fetch": "3.3.2",
|
||||
"rimraf": "6.1.3",
|
||||
"showdown": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz",
|
||||
"integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.2.tgz",
|
||||
"integrity": "sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"jackspeak": "^4.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz",
|
||||
"integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/cheerio": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz",
|
||||
"integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cheerio-select": "^2.1.0",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.2.2",
|
||||
"encoding-sniffer": "^0.2.1",
|
||||
"htmlparser2": "^10.1.0",
|
||||
"parse5": "^7.3.0",
|
||||
"parse5-htmlparser2-tree-adapter": "^7.1.0",
|
||||
"parse5-parser-stream": "^7.1.2",
|
||||
"undici": "^7.19.0",
|
||||
"whatwg-mimetype": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.18.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cheerio-select": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
|
||||
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-select": "^5.1.0",
|
||||
"css-what": "^6.1.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "9.5.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
|
||||
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/css-select": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
|
||||
"integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "^6.1.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"domutils": "^3.0.1",
|
||||
"nth-check": "^2.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/css-what": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
|
||||
"integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/data-uri-to-buffer": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/domhandler": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
|
||||
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/draftlog": {
|
||||
"version": "1.0.13",
|
||||
"resolved": "https://registry.npmjs.org/draftlog/-/draftlog-1.0.13.tgz",
|
||||
"integrity": "sha512-GeMWOpXERBpfVDK6v7m0x1hPg8+g8ZsZWqJl2T17wHqrm4h8fnjiZmXcnCrmwogAc6R3YTxFXax15wezfuyCUw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/encoding-sniffer": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
|
||||
"integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iconv-lite": "^0.6.3",
|
||||
"whatwg-encoding": "^3.1.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "paypal",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-domexception": "^1.0.0",
|
||||
"web-streams-polyfill": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20 || >= 14.13"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fetch-blob": "^3.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "11.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz",
|
||||
"integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^6.0.1",
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "13.0.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-13.0.3.tgz",
|
||||
"integrity": "sha512-/g3B0mC+4x724v1TgtBlBtt2hPi/EWptsIAmXUx9Z2rvBYleQcsrmaOzd5LyL50jf/Soi83ZDJmw2+XqvH/EeA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"minimatch": "^10.2.0",
|
||||
"minipass": "^7.1.2",
|
||||
"path-scurry": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz",
|
||||
"integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==",
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.2.2",
|
||||
"entities": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2/node_modules/entities": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
|
||||
"integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz",
|
||||
"integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
|
||||
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "11.2.6",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
|
||||
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz",
|
||||
"integrity": "sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^5.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "18 || 20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"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==",
|
||||
"deprecated": "Use your platform's native DOMException instead",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jimmywarting"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://paypal.me/jimmywarting"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
|
||||
"integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"data-uri-to-buffer": "^4.0.0",
|
||||
"fetch-blob": "^3.1.4",
|
||||
"formdata-polyfill": "^4.0.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/node-fetch"
|
||||
}
|
||||
},
|
||||
"node_modules/nth-check": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/nth-check?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/package-json-from-dist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
|
||||
"license": "BlueOak-1.0.0"
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
|
||||
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"entities": "^6.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5-htmlparser2-tree-adapter": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
|
||||
"integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domhandler": "^5.0.3",
|
||||
"parse5": "^7.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5-parser-stream": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
|
||||
"integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"parse5": "^7.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5/node_modules/entities": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
|
||||
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz",
|
||||
"integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^11.0.0",
|
||||
"minipass": "^7.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.1.3.tgz",
|
||||
"integrity": "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"glob": "^13.0.3",
|
||||
"package-json-from-dist": "^1.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/showdown": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz",
|
||||
"integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^9.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"showdown": "bin/showdown.js"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://www.paypal.me/tiviesantos"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.19.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.19.1.tgz",
|
||||
"integrity": "sha512-Gpq0iNm5M6cQWlyHQv9MV+uOj1jWk7LpkoE5vSp/7zjb4zMdAcUD+VL5y0nH4p9EbUklq00eVIIX/XcDHzu5xg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.18.1"
|
||||
}
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||
"integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-encoding": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
||||
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iconv-lite": "0.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-mimetype": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
|
||||
"integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
package.json
30
package.json
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"name": "awesome-docker-website",
|
||||
"version": "1.0.0",
|
||||
"description": "A curated list of Docker resources and projects Inspired by @sindresorhus and improved by amazing contributors",
|
||||
"main": "build.js",
|
||||
"scripts": {
|
||||
"build": "rimraf ./dist/ && node build.js",
|
||||
"test-pr": "node tests/pull_request.mjs",
|
||||
"test": "node tests/test_all.mjs",
|
||||
"health-check": "node tests/health_check.mjs"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/veggiemonk/awesome-docker.git"
|
||||
},
|
||||
"author": "Julien Bisconti <julien.bisconti at hotmail dot com>",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/veggiemonk/awesome-docker/issues"
|
||||
},
|
||||
"homepage": "https://github.com/veggiemonk/awesome-docker#readme",
|
||||
"dependencies": {
|
||||
"cheerio": "1.2.0",
|
||||
"draftlog": "1.0.13",
|
||||
"fs-extra": "11.3.3",
|
||||
"node-fetch": "3.3.2",
|
||||
"rimraf": "6.1.3",
|
||||
"showdown": "^2.1.0"
|
||||
}
|
||||
}
|
||||
108
tests/common.mjs
108
tests/common.mjs
@@ -1,108 +0,0 @@
|
||||
import fetch from 'node-fetch';
|
||||
import { isRedirect } from 'node-fetch';
|
||||
import {readFileSync} from 'fs';
|
||||
|
||||
const LINKS_OPTIONS = {
|
||||
redirect: 'manual',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'user-agent':
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
|
||||
},
|
||||
timeout: 60000, // 1m
|
||||
signal: AbortSignal.timeout(60000),
|
||||
};
|
||||
|
||||
const LOG = {
|
||||
error: (...args) => console.error('❌ ERROR', args),
|
||||
error_string: (...args) =>
|
||||
console.error('❌ ERROR', JSON.stringify({ ...args }, null, ' ')),
|
||||
debug: (...args) => {
|
||||
if (process.env.DEBUG) console.log('>>> DEBUG: ', { ...args });
|
||||
},
|
||||
debug_string: (...args) => {
|
||||
if (process.env.DEBUG)
|
||||
console.log('>>> DEBUG: ', JSON.stringify({ ...args }, null, ' '));
|
||||
},
|
||||
};
|
||||
|
||||
const handleFailure = (error) => {
|
||||
console.error(`${error.message}: ${error.stack}`, { error });
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
process.on('unhandledRejection', handleFailure);
|
||||
|
||||
const extract_all_links = (markdown) => {
|
||||
// if you have a problem and you try to solve it with a regex,
|
||||
// now you have two problems
|
||||
// TODO: replace this mess with a mardown parser ?
|
||||
const re = /(((https:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w\-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/@\-\\\w]*))?)/g;
|
||||
return markdown.match(re);
|
||||
};
|
||||
|
||||
const find_duplicates = (arr) => {
|
||||
const hm = {};
|
||||
const dup = [];
|
||||
arr.forEach((e) => {
|
||||
if (hm[e]) dup.push(e);
|
||||
else hm[e] = true;
|
||||
});
|
||||
return dup;
|
||||
};
|
||||
|
||||
const partition = (arr, func) => {
|
||||
const ap = [[], []];
|
||||
arr.forEach((e) => (func(e) ? ap[0].push(e) : ap[1].push(e)));
|
||||
return ap;
|
||||
};
|
||||
|
||||
async function fetch_link(url) {
|
||||
try {
|
||||
const { headers, ok, status, statusText } = await fetch(url, LINKS_OPTIONS);
|
||||
const redirect = isRedirect(status) ? { redirect: { src: url, dst: headers.get("location") } } : {};
|
||||
return [url, { ok, status: statusText, ...redirect }];
|
||||
} catch (error) {
|
||||
return [url, { ok: false, status: error.message }];
|
||||
}
|
||||
}
|
||||
|
||||
async function batch_fetch({ arr, get, post_filter_func, BATCH_SIZE = 8 }) {
|
||||
const result = [];
|
||||
/* eslint-disable no-await-in-loop */
|
||||
for (let i = 0; i < arr.length; i += BATCH_SIZE) {
|
||||
const batch = arr.slice(i, i + BATCH_SIZE);
|
||||
LOG.debug_string({ batch });
|
||||
let res = await Promise.all(batch.map(get));
|
||||
console.log(`batch fetched...${i + BATCH_SIZE}`);
|
||||
res = post_filter_func ? res.filter(post_filter_func) : res;
|
||||
LOG.debug_string({ res });
|
||||
result.push(...res);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const data = readFileSync('./tests/exclude_in_test.json')
|
||||
const exclude = JSON.parse(data)
|
||||
const exclude_length = exclude.length;
|
||||
const exclude_from_list = (link) => {
|
||||
let is_excluded = false;
|
||||
for (let i = 0; i < exclude_length; i += 1) {
|
||||
if (link.startsWith(exclude[i])) {
|
||||
is_excluded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return is_excluded;
|
||||
};
|
||||
|
||||
export default {
|
||||
LOG,
|
||||
handleFailure,
|
||||
extract_all_links,
|
||||
find_duplicates,
|
||||
partition,
|
||||
fetch_link,
|
||||
batch_fetch,
|
||||
exclude_from_list,
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
[
|
||||
"https://vimeo.com",
|
||||
"https://travis-ci.org/veggiemonk/awesome-docker.svg",
|
||||
"https://github.com/apps/",
|
||||
"https://twitter.com",
|
||||
"https://www.meetup.com/",
|
||||
"https://cycle.io/",
|
||||
"https://www.manning.com/",
|
||||
"https://deepfence.io",
|
||||
"https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg",
|
||||
"https://www.se-radio.net/2017/05/se-radio-episode-290-diogo-monica-on-docker-security",
|
||||
"https://www.reddit.com/r/docker/",
|
||||
"https://www.udacity.com/course/scalable-microservices-with-kubernetes--ud615",
|
||||
"https://www.youtube.com/playlist",
|
||||
"https://www.aquasec.com",
|
||||
"https://cloudsmith.com"
|
||||
]
|
||||
@@ -1,206 +0,0 @@
|
||||
import fs from 'fs-extra';
|
||||
import fetch from 'node-fetch';
|
||||
import helper from './common.mjs';
|
||||
|
||||
const README = 'README.md';
|
||||
const GITHUB_GQL_API = 'https://api.github.com/graphql';
|
||||
const TOKEN = process.env.GITHUB_TOKEN || '';
|
||||
|
||||
if (!TOKEN) {
|
||||
console.error('GITHUB_TOKEN environment variable is required');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const Authorization = `token ${TOKEN}`;
|
||||
|
||||
const LOG = {
|
||||
info: (...args) => console.log('ℹ️ ', ...args),
|
||||
warn: (...args) => console.warn('⚠️ ', ...args),
|
||||
error: (...args) => console.error('❌', ...args),
|
||||
};
|
||||
|
||||
// Extract GitHub repos from links
|
||||
const extract_repos = (arr) =>
|
||||
arr
|
||||
.map((e) => e.substr('https://github.com/'.length).split('/'))
|
||||
.filter((r) => r.length === 2 && r[1] !== '');
|
||||
|
||||
// Generate GraphQL query to check repo health
|
||||
const generate_health_query = (repos) => {
|
||||
const repoQueries = repos.map(([owner, name]) => {
|
||||
const safeName = `repo_${owner.replace(/(-|\.)/g, '_')}_${name.replace(/(-|\.)/g, '_')}`;
|
||||
return `${safeName}: repository(owner: "${owner}", name:"${name}"){
|
||||
nameWithOwner
|
||||
isArchived
|
||||
pushedAt
|
||||
createdAt
|
||||
stargazerCount
|
||||
forkCount
|
||||
isDisabled
|
||||
isFork
|
||||
isLocked
|
||||
isPrivate
|
||||
}`;
|
||||
}).join('\n');
|
||||
|
||||
return `query REPO_HEALTH { ${repoQueries} }`;
|
||||
};
|
||||
|
||||
// Batch repos into smaller chunks for GraphQL
|
||||
function* batchRepos(repos, size = 50) {
|
||||
for (let i = 0; i < repos.length; i += size) {
|
||||
yield repos.slice(i, i + size);
|
||||
}
|
||||
}
|
||||
|
||||
async function checkRepoHealth(repos) {
|
||||
const results = {
|
||||
archived: [],
|
||||
stale: [], // No commits in 2+ years
|
||||
inactive: [], // No commits in 1-2 years
|
||||
healthy: [],
|
||||
disabled: [],
|
||||
total: repos.length,
|
||||
};
|
||||
|
||||
const twoYearsAgo = new Date();
|
||||
twoYearsAgo.setFullYear(twoYearsAgo.getFullYear() - 2);
|
||||
|
||||
const oneYearAgo = new Date();
|
||||
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
|
||||
|
||||
LOG.info(`Checking health of ${repos.length} repositories...`);
|
||||
|
||||
for (const batch of batchRepos(repos)) {
|
||||
const query = generate_health_query(batch);
|
||||
const options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ query }),
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await fetch(GITHUB_GQL_API, options);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.errors) {
|
||||
LOG.error('GraphQL errors:', data.errors);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const [key, repo] of Object.entries(data.data)) {
|
||||
if (!repo) continue;
|
||||
|
||||
const pushedAt = new Date(repo.pushedAt);
|
||||
const repoInfo = {
|
||||
name: repo.nameWithOwner,
|
||||
pushedAt: repo.pushedAt,
|
||||
stars: repo.stargazerCount,
|
||||
url: `https://github.com/${repo.nameWithOwner}`,
|
||||
};
|
||||
|
||||
if (repo.isArchived) {
|
||||
results.archived.push(repoInfo);
|
||||
} else if (repo.isDisabled) {
|
||||
results.disabled.push(repoInfo);
|
||||
} else if (pushedAt < twoYearsAgo) {
|
||||
results.stale.push(repoInfo);
|
||||
} else if (pushedAt < oneYearAgo) {
|
||||
results.inactive.push(repoInfo);
|
||||
} else {
|
||||
results.healthy.push(repoInfo);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
LOG.error('Batch fetch error:', error.message);
|
||||
}
|
||||
|
||||
// Rate limiting - wait a bit between batches
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
function generateReport(results) {
|
||||
const report = [];
|
||||
|
||||
report.push('# 🏥 Awesome Docker - Health Check Report\n');
|
||||
report.push(`**Generated:** ${new Date().toISOString()}\n`);
|
||||
report.push(`**Total Repositories:** ${results.total}\n`);
|
||||
|
||||
report.push('\n## 📊 Summary\n');
|
||||
report.push(`- ✅ Healthy (updated in last year): ${results.healthy.length}`);
|
||||
report.push(`- ⚠️ Inactive (1-2 years): ${results.inactive.length}`);
|
||||
report.push(`- 🪦 Stale (2+ years): ${results.stale.length}`);
|
||||
report.push(`- 📦 Archived: ${results.archived.length}`);
|
||||
report.push(`- 🚫 Disabled: ${results.disabled.length}\n`);
|
||||
|
||||
if (results.archived.length > 0) {
|
||||
report.push('\n## 📦 Archived Repositories (Should mark as :skull:)\n');
|
||||
results.archived.forEach(repo => {
|
||||
report.push(`- [${repo.name}](${repo.url}) - ⭐ ${repo.stars} - Last push: ${repo.pushedAt}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (results.stale.length > 0) {
|
||||
report.push('\n## 🪦 Stale Repositories (No activity in 2+ years)\n');
|
||||
results.stale.slice(0, 50).forEach(repo => {
|
||||
report.push(`- [${repo.name}](${repo.url}) - ⭐ ${repo.stars} - Last push: ${repo.pushedAt}`);
|
||||
});
|
||||
if (results.stale.length > 50) {
|
||||
report.push(`\n... and ${results.stale.length - 50} more`);
|
||||
}
|
||||
}
|
||||
|
||||
if (results.inactive.length > 0) {
|
||||
report.push('\n## ⚠️ Inactive Repositories (No activity in 1-2 years)\n');
|
||||
report.push('_These may still be stable/complete projects - review individually_\n');
|
||||
results.inactive.slice(0, 30).forEach(repo => {
|
||||
report.push(`- [${repo.name}](${repo.url}) - ⭐ ${repo.stars} - Last push: ${repo.pushedAt}`);
|
||||
});
|
||||
if (results.inactive.length > 30) {
|
||||
report.push(`\n... and ${results.inactive.length - 30} more`);
|
||||
}
|
||||
}
|
||||
|
||||
return report.join('\n');
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const markdown = await fs.readFile(README, 'utf8');
|
||||
let links = helper.extract_all_links(markdown);
|
||||
|
||||
const github_links = links.filter(link =>
|
||||
link.startsWith('https://github.com') &&
|
||||
!helper.exclude_from_list(link) &&
|
||||
!link.includes('/issues') &&
|
||||
!link.includes('/pull') &&
|
||||
!link.includes('/wiki') &&
|
||||
!link.includes('#')
|
||||
);
|
||||
|
||||
const repos = extract_repos(github_links);
|
||||
const results = await checkRepoHealth(repos);
|
||||
|
||||
const report = generateReport(results);
|
||||
|
||||
// Save report
|
||||
await fs.writeFile('HEALTH_REPORT.md', report);
|
||||
LOG.info('Health report saved to HEALTH_REPORT.md');
|
||||
|
||||
// Also print summary to console
|
||||
console.log('\n' + report);
|
||||
|
||||
// Exit with error if there are actionable items
|
||||
if (results.archived.length > 0 || results.stale.length > 10) {
|
||||
LOG.warn(`Found ${results.archived.length} archived and ${results.stale.length} stale repos`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Starting health check...');
|
||||
main();
|
||||
@@ -1,69 +0,0 @@
|
||||
import fs from 'fs-extra';
|
||||
import helper from './common.mjs';
|
||||
|
||||
console.log({
|
||||
DEBUG: process.env.DEBUG || false,
|
||||
});
|
||||
|
||||
const README = 'README.md';
|
||||
|
||||
async function main() {
|
||||
const has_error = {
|
||||
show: false,
|
||||
duplicates: '',
|
||||
other_links_error: '',
|
||||
};
|
||||
const markdown = await fs.readFile(README, 'utf8');
|
||||
let links = helper.extract_all_links(markdown);
|
||||
links = links.filter((l) => !helper.exclude_from_list(l)); // exclude websites
|
||||
helper.LOG.debug_string({ links });
|
||||
|
||||
console.log(`total links to check ${links.length}`);
|
||||
|
||||
console.log('checking for duplicates links...');
|
||||
|
||||
const duplicates = helper.find_duplicates(links);
|
||||
if (duplicates.length > 0) {
|
||||
has_error.show = true;
|
||||
has_error.duplicates = duplicates;
|
||||
}
|
||||
helper.LOG.debug_string({ duplicates });
|
||||
const [github_links, external_links] = helper.partition(links, (link) =>
|
||||
link.startsWith('https://github.com'),
|
||||
);
|
||||
|
||||
console.log(`checking ${external_links.length} external links...`);
|
||||
|
||||
const external_links_error = await helper.batch_fetch({
|
||||
arr: external_links,
|
||||
get: helper.fetch_link,
|
||||
post_filter_func: (x) => !x[1].ok,
|
||||
BATCH_SIZE: 8,
|
||||
});
|
||||
if (external_links_error.length > 0) {
|
||||
has_error.show = true;
|
||||
has_error.other_links_error = external_links_error;
|
||||
}
|
||||
|
||||
console.log(`checking ${github_links.length} GitHub repositories...`);
|
||||
|
||||
console.log(
|
||||
`skipping GitHub repository check. Run "npm run test" to execute them manually.`,
|
||||
);
|
||||
|
||||
console.log({
|
||||
TEST_PASSED: !has_error.show,
|
||||
EXTERNAL_LINKS: external_links.length,
|
||||
});
|
||||
|
||||
if (has_error.show) {
|
||||
helper.LOG.error_string(has_error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('starting...');
|
||||
main().catch((error) => {
|
||||
console.error('Fatal error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,127 +0,0 @@
|
||||
import fs from 'fs-extra';
|
||||
import fetch from 'node-fetch';
|
||||
import helper from './common.mjs';
|
||||
|
||||
function envvar_undefined(variable_name) {
|
||||
throw new Error(`${variable_name} must be defined`);
|
||||
}
|
||||
|
||||
console.log({
|
||||
DEBUG: process.env.DEBUG || false,
|
||||
});
|
||||
|
||||
const README = 'README.md';
|
||||
const GITHUB_GQL_API = 'https://api.github.com/graphql';
|
||||
const TOKEN = process.env.GITHUB_TOKEN || envvar_undefined('GITHUB_TOKEN');
|
||||
|
||||
const Authorization = `token ${TOKEN}`;
|
||||
|
||||
const make_GQL_options = (query) => ({
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization,
|
||||
'Content-Type': 'application/json',
|
||||
'user-agent':
|
||||
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
|
||||
},
|
||||
body: JSON.stringify({ query }),
|
||||
});
|
||||
|
||||
const extract_repos = (arr) =>
|
||||
arr
|
||||
.map((e) => e.substr('https://github.com/'.length).split('/'))
|
||||
.filter((r) => r.length === 2 && r[1] !== '');
|
||||
|
||||
const generate_GQL_query = (arr) =>
|
||||
`query AWESOME_REPOS{ ${arr
|
||||
.map(
|
||||
([owner, name]) =>
|
||||
`repo_${owner.replace(/(-|\.)/g, '_')}_${name.replace(
|
||||
/(-|\.)/g,
|
||||
'_',
|
||||
)}: repository(owner: "${owner}", name:"${name}"){ nameWithOwner isArchived } `,
|
||||
)
|
||||
.join('')} }`;
|
||||
|
||||
async function main() {
|
||||
const has_error = {
|
||||
show: false,
|
||||
duplicates: '',
|
||||
other_links_error: '',
|
||||
github_repos: '',
|
||||
};
|
||||
const markdown = await fs.readFile(README, 'utf8');
|
||||
let links = helper.extract_all_links(markdown);
|
||||
links = links.filter((l) => !helper.exclude_from_list(l)); // exclude websites
|
||||
helper.LOG.debug_string({ links });
|
||||
|
||||
console.log(`total links to check ${links.length}`);
|
||||
|
||||
console.log('checking for duplicates links...');
|
||||
|
||||
const duplicates = helper.find_duplicates(links);
|
||||
if (duplicates.length > 0) {
|
||||
has_error.show = true;
|
||||
has_error.duplicates = duplicates;
|
||||
}
|
||||
helper.LOG.debug_string({ duplicates });
|
||||
const [github_links, external_links] = helper.partition(links, (link) =>
|
||||
link.startsWith('https://github.com'),
|
||||
);
|
||||
|
||||
console.log(`checking ${external_links.length} external links...`);
|
||||
|
||||
const external_links_error = await helper.batch_fetch({
|
||||
arr: external_links,
|
||||
get: helper.fetch_link,
|
||||
post_filter_func: (x) => !x[1].ok,
|
||||
BATCH_SIZE: 8,
|
||||
});
|
||||
if (external_links_error.length > 0) {
|
||||
has_error.show = true;
|
||||
has_error.other_links_error = external_links_error;
|
||||
}
|
||||
|
||||
console.log(`checking ${github_links.length} GitHub repositories...`);
|
||||
|
||||
const repos = extract_repos(github_links);
|
||||
const query = generate_GQL_query(repos);
|
||||
const options = make_GQL_options(query);
|
||||
const gql_response = await fetch(GITHUB_GQL_API, options).then((r) =>
|
||||
r.json(),
|
||||
);
|
||||
if (gql_response.errors) {
|
||||
has_error.show = true;
|
||||
has_error.github_repos = gql_response.errors;
|
||||
}
|
||||
|
||||
// Check for archived repositories
|
||||
console.log('checking for archived repositories...');
|
||||
const archived_repos = [];
|
||||
if (gql_response.data) {
|
||||
for (const [key, repo] of Object.entries(gql_response.data)) {
|
||||
if (repo && repo.isArchived) {
|
||||
archived_repos.push(repo.nameWithOwner);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (archived_repos.length > 0) {
|
||||
console.warn(`⚠️ Found ${archived_repos.length} archived repositories that should be marked with :skull:`);
|
||||
console.warn('Archived repos:', archived_repos);
|
||||
// Don't fail the build, just warn
|
||||
}
|
||||
|
||||
console.log({
|
||||
TEST_PASSED: has_error.show,
|
||||
GITHUB_REPOSITORY: github_links.length,
|
||||
EXTERNAL_LINKS: external_links.length,
|
||||
});
|
||||
|
||||
if (has_error.show) {
|
||||
helper.LOG.error_string(has_error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('starting...');
|
||||
main();
|
||||
@@ -1,229 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="no-js" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="Cache-control" content="public" />
|
||||
<meta charset="UTF-8" />
|
||||
<title>Awesome-docker</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#5DBCD2" />
|
||||
<meta
|
||||
name="description"
|
||||
content="A curated list of Docker resources and projects."
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="free and open-source open source projects for docker moby kubernetes linux awesome awesome-list container tools dockerfile list moby docker-container docker-image docker-environment docker-deployment docker-swarm docker-api docker-monitoring docker-machine docker-security docker-registry"
|
||||
/>
|
||||
<meta
|
||||
name="google-site-verification"
|
||||
content="_yiugvz0gCtfsBLyLl1LnkALXb6D4ofiwCyV1XOlYBM"
|
||||
/>
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: Open Sans, Helvetica Neue, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #606c71;
|
||||
}
|
||||
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
color: #5dbcd2;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
margin-bottom: 1rem;
|
||||
color: hsla(0, 0%, 100%, 0.7);
|
||||
background-color: hsla(0, 0%, 100%, 0.08);
|
||||
border: 1px solid hsla(0, 0%, 100%, 0.2);
|
||||
border-radius: 0.3rem;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background-color: #5dbcd2;
|
||||
background-image: linear-gradient(120deg, #155799, #5dbcd2);
|
||||
}
|
||||
|
||||
.project-name {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.1rem;
|
||||
}
|
||||
|
||||
.project-tagline {
|
||||
margin-bottom: 2rem;
|
||||
font-weight: 400;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.main-content :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.main-content h1,
|
||||
.main-content h4 {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 400;
|
||||
color: #5dbcd2;
|
||||
}
|
||||
|
||||
.main-content p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.main-content blockquote {
|
||||
padding: 0 1rem;
|
||||
margin-left: 0;
|
||||
color: #819198;
|
||||
border-left: 0.3rem solid #dce6f0;
|
||||
}
|
||||
|
||||
.main-content blockquote > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.main-content blockquote > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.main-content img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 64em) {
|
||||
.btn {
|
||||
padding: 0.75rem 1rem;
|
||||
}
|
||||
.page-header {
|
||||
padding: 5rem 6rem;
|
||||
}
|
||||
.project-name {
|
||||
font-size: 3.25rem;
|
||||
}
|
||||
.project-tagline {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
.main-content {
|
||||
max-width: 64rem;
|
||||
padding: 2rem 6rem;
|
||||
margin: 0 auto;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 42em) and (max-width: 64em) {
|
||||
.btn {
|
||||
padding: 0.6rem 0.9rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.page-header {
|
||||
padding: 3rem 4rem;
|
||||
}
|
||||
.project-name {
|
||||
font-size: 2.25rem;
|
||||
}
|
||||
.project-tagline {
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
.main-content {
|
||||
padding: 2rem 4rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 42em) {
|
||||
.btn {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.page-header {
|
||||
padding: 2rem 1rem;
|
||||
}
|
||||
.project-name {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
.project-tagline {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.main-content {
|
||||
padding: 2rem 1rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section class="page-header">
|
||||
<h1 class="project-name">Awesome-docker</h1>
|
||||
<h2 class="project-tagline">
|
||||
A curated list of Docker resources and projects
|
||||
</h2>
|
||||
<a href="https://github.com/veggiemonk/awesome-docker" class="btn"
|
||||
>View on GitHub</a
|
||||
>
|
||||
<br />
|
||||
<!-- Place this tag where you want the button to render. -->
|
||||
<a
|
||||
class="github-button"
|
||||
href="https://github.com/veggiemonk/awesome-docker#readme"
|
||||
data-icon="octicon-star"
|
||||
data-size="large"
|
||||
data-count-href="/veggiemonk/awesome-docker/stargazers"
|
||||
data-show-count="true"
|
||||
data-count-aria-label="# stargazers on GitHub"
|
||||
aria-label="Star veggiemonk/awesome-docker on GitHub"
|
||||
>Star</a
|
||||
>
|
||||
</section>
|
||||
<section id="md" class="main-content"></section>
|
||||
<!--<script src="index.js"></script> -->
|
||||
<!--Place this tag in your head or just before your close body tag. -->
|
||||
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user