Commit c4be73a
Changed files (10)
.github
workflows
scripts
test
.github/workflows/test.yml
@@ -13,3 +13,5 @@ jobs:
run: npm run build
- name: Check all images exist
run: npm run check-images
+ - name: Run unit tests
+ run: npm run test:unit
scripts/test.mjs
@@ -0,0 +1,15 @@
+#!/usr/bin/env node
+
+import glob from 'fast-glob'
+import { pathToFileURL } from 'node:url'
+
+const focused = process.argv.slice(2)
+const suites = focused.length
+ ? focused
+ : await glob('test/**/*.test.{ts,cjs,mjs}', {
+ cwd: process.cwd(),
+ absolute: true,
+ onlyFiles: true,
+ })
+
+await Promise.all(suites.map((suite) => import(pathToFileURL(suite))))
src/all-badges/index.ts
@@ -13,3 +13,5 @@ export const allBadges = [
await import('./chore-commit/chore-commit.js'),
await import('./delorean/delorean.js'),
] as const
+
+export const names = allBadges.flatMap(({ default: { badges } }) => badges)
src/badges.ts
@@ -29,11 +29,30 @@ export type Badge = {
image: string
}
-export function badgeCollection(badges: Badge[], baseUrl: URL) {
+const voidGrant = {
+ evidence() {},
+ evidenceCommits() {},
+ evidenceCommitsWithMessage() {},
+ evidencePRs() {},
+}
+
+export function badgeCollection(
+ badges: Badge[],
+ baseUrl: URL,
+ pickBadges: string[],
+ omitBadges: string[],
+) {
const indexes = new Map(badges.map((x, i) => [x.id, i]))
const baseDir = path.basename(path.dirname(fileURLToPath(baseUrl)))
return function grant(id: ID, desc: string) {
+ if (!pickBadges.includes(id) || omitBadges.includes(id)) {
+ if (indexes.has(id)) {
+ badges.splice(indexes.get(id)!, 1)
+ }
+ return voidGrant
+ }
+
const badge: Badge = {
id,
desc,
src/main.ts
@@ -6,7 +6,7 @@ import { Octokit, RequestError } from 'octokit'
import { retry } from '@octokit/plugin-retry'
import { throttling } from '@octokit/plugin-throttling'
import { collect, Data } from './collect/collect.js'
-import { allBadges } from './all-badges/index.js'
+import { allBadges, names } from './all-badges/index.js'
import { Badge, badgeCollection } from './badges.js'
import { updateReadme } from './update-readme.js'
import { updateBadges } from './update-badges.js'
@@ -14,7 +14,7 @@ import { updateBadges } from './update-badges.js'
void (async function main() {
const { env } = process
const argv = minimist(process.argv.slice(2), {
- string: ['data', 'repo', 'token', 'size', 'user'],
+ string: ['data', 'repo', 'token', 'size', 'user', 'pick', 'omit'],
boolean: ['dryrun'],
})
const {
@@ -24,8 +24,12 @@ void (async function main() {
data: dataPath = '',
size,
dryrun,
+ pick,
+ omit,
} = argv
const [owner, repo] = repository?.split('/', 2) || [username, username]
+ const pickBadges = pick ? pick.split(',') : names
+ const omitBadges = omit ? omit.split(',') : []
const MyOctokit = Octokit.plugin(retry, throttling)
const octokit = new MyOctokit({
@@ -96,7 +100,7 @@ void (async function main() {
}
for (const { default: presenter } of allBadges) {
- const grant = badgeCollection(badges, presenter.url)
+ const grant = badgeCollection(badges, presenter.url, pickBadges, omitBadges)
presenter.present(data, grant)
}
console.log('Badges', badges)
test/badges.test.ts
@@ -0,0 +1,71 @@
+import * as assert from 'node:assert'
+import { describe, it } from 'node:test'
+import { allBadges, names } from '../src/all-badges/index.js'
+import { Badge, badgeCollection } from '../src/badges.js'
+import abcPresenter from '../src/all-badges/abc-commit/abc-commit.js'
+
+describe('badges', () => {
+ it('exposes all badges presenters', () => {
+ const expected = [
+ 'a-commit',
+ 'ab-commit',
+ 'abc-commit',
+ 'abcd-commit',
+ 'abcde-commit',
+ 'abcdef-commit',
+ 'stars-100',
+ 'stars-500',
+ 'stars-1000',
+ 'stars-2000',
+ 'stars-5000',
+ 'stars-10000',
+ 'stars-20000',
+ 'midnight-commits',
+ 'morning-commits',
+ 'evening-commits',
+ 'yeti',
+ 'star-gazer',
+ 'dead-commit',
+ 'bad-words',
+ 'mass-delete-commit',
+ 'mass-delete-commit-10k',
+ 'revert-revert-commit',
+ 'my-badges-contributor',
+ 'fix-2',
+ 'fix-3',
+ 'fix-4',
+ 'fix-5',
+ 'fix-6',
+ 'fix-6+',
+ ]
+
+ assert.deepEqual(names, expected)
+ })
+
+ it('grant respects pick and omit params', () => {
+ const badges: Badge[] = []
+ const presenter = abcPresenter
+ const pickBadges = ['a-commit', 'ab-commit', 'abc-commit', 'abcd-commit']
+ const omitBadges = ['ab-commit', 'abc-commit']
+ const grant = badgeCollection(badges, presenter.url, pickBadges, omitBadges)
+
+ abcPresenter.badges.forEach((badge) => grant(badge, 'test'))
+
+ assert.deepEqual(badges, [
+ {
+ id: 'a-commit',
+ desc: 'test',
+ body: '',
+ image:
+ 'https://github.com/my-badges/my-badges/blob/master/src/all-badges/abc-commit/a-commit.png?raw=true',
+ },
+ {
+ id: 'abcd-commit',
+ desc: 'test',
+ body: '',
+ image:
+ 'https://github.com/my-badges/my-badges/blob/master/src/all-badges/abc-commit/abcd-commit.png?raw=true',
+ },
+ ])
+ })
+})
.gitignore
@@ -2,3 +2,4 @@
/data/
/dist/
yarn.lock
+coverage
package.json
@@ -14,7 +14,8 @@
"build": "npm run copy-files && npm run tsc",
"copy-files": "copyfiles -u 1 src/**/*.graphql dist/",
"check-images": "node dist/check-images.js",
- "test": "node test.js",
+ "test": "test:unit",
+ "test:unit": "c8 -r lcov -r text -o coverage -x scripts -x test node --loader ts-node/esm --experimental-specifier-resolution=node scripts/test.mjs",
"release": "release-it"
},
"dependencies": {
@@ -27,8 +28,12 @@
"@octokit/graphql-schema": "^14.33.0",
"@types/minimist": "^1.2.3",
"@types/node": "^20.8.0",
+ "c8": "^8.0.1",
"copyfiles": "^2.4.1",
+ "fast-glob": "^3.3.1",
"prettier": "^3.0.3",
+ "release-it": "^16.2.1",
+ "ts-node": "^10.9.1",
"typescript": "^5.2.2"
},
"files": [
README.md
@@ -92,14 +92,16 @@ jobs:
- Start **my-badges** workflow, or wait for it to run automatically.
## Configuration
-| Param | ENV alias | Description | Default |
-|----------|----------------|------------------------------------------------------------------------------------------|---------------|
-| `token` | `GITHUB_TOKEN` | Auth token | |
-| `user` | `GITHUB_USER` | Username | |
-| `repo` | `GITHUB_REPO` | Repository name to push badges | `{user/user}` |
-| `data` | | Path to JSON to generate badges. If empty, required data will be obtained from the GH API | |
-| `size` | | Badge size for README.md, px | 64 |
-| `dryrun` | | Generate badges, but skip pushing to git | |
+| Param | ENV alias | Description | Default |
+|----------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
+| `token` | `GITHUB_TOKEN` | Auth token | |
+| `user` | `GITHUB_USER` | Username | |
+| `repo` | `GITHUB_REPO` | Repository name to push badges | `{user/user}` |
+| `data` | | Path to JSON to generate badges. If empty, required data will be obtained from the GH API | |
+| `size` | | Badge size for README.md, px | 64 |
+| `dryrun` | | Generate badges, but skip pushing to git | |
+| `pick` | | List of badges to pick. Pass `--pick="a-commit,ab-commit,revert-revert-commit"` to generate only the specified entries. If empty gets all of them | |
+| `omit` | | List of badges to exclude. For example, if you're too shy to flex your stars: `--omit:stars-100,stars-500,stars-1000` | |
## Contributing badges
tsconfig.json
@@ -6,7 +6,8 @@
"module": "NodeNext",
"strict": true,
"outDir": "./dist",
- "declaration": false
+ "declaration": false,
+ "allowJs": true
},
"include": ["./src/**/*"]
}