Skip to content

fix: repair CLI crashes, unify schema v2, add normalization pipeline and expanded tests (v1.1.0) - #1

Open
uthumany wants to merge 2 commits into
mainfrom
improve/fix-and-schema-unify
Open

uthumany wants to merge 2 commits into
mainfrom
improve/fix-and-schema-unify

Conversation

@uthumany

@uthumany uthumany commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Summary

Implements the prioritized fixes from the repository review:

Bug fixes

  • stats and export CLI commands no longer crash
  • getSvgPath() now resolves to verified bundled files (null for remote-only icons)
  • Search relevance capped at 100; negative counts rejected with exit code 1
  • --version/-v handled correctly; ANSI colors only on TTYs

Data quality

  • New idempotent normalization pipeline (npm run normalize): 874 duplicate SVGs removed, 284 name-file mismatches flagged, 12 wrong names self-corrected, 9,800+ tags generated
  • Unified schema v2 with license/quality fields; verified on every run

Testing & docs

  • 45 tests passing (was 14), 0 lint errors
  • README corrected to actual sources; uhumanβ†’uthumany; THIRD_PARTY_NOTICES.md added

Local verification: npm test 45/45 pass, npm run lint 0 errors, pipeline run clean (9,810 icons).


Devin Review

… add normalization pipeline and 31 tests

- fix(stats): read breakdown.byType/bySource/topCategories shape the CLI expects
- fix(export): import correct exporter functions (toJson/toCsv/toMarkdown)
- fix(getSvgPath): use verified local_path from schema v2; null for remote icons
- fix(search): cap relevance at 100; add tag/offset filters
- fix(cli): reject negative counts, handle --version/-v boolean flags, TTY-gated ANSI
- fix(loader): load normalized schema-v2 database, add clearCache/getSvgDir
- fix(stats): unique ids, correct pack counting, sources field
- feat(normalize): 10-stage idempotent pipeline (scripts/normalize-data.js, docs/PIPELINE.md)
  * 874 duplicate SVGs removed (5237 -> 4363), 284 name mismatches flagged,
    12 names self-corrected, 4 correction collisions removed, 9800+ tags generated
- feat(api): filterByTag, listSources, input validation, Fisher-Yates shuffle
- test: expand suite 14 -> 45 (schema contracts, exporter, CLI subprocess)
- docs: fix README overclaims, uthuman -> uthumany, THIRD_PARTY_NOTICES.md,
  CHANGELOG v1.1.0; bump version to 1.1.0
@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review available on request

  • πŸ” Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

βš™οΈ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a78ad7e5-615d-4c18-8f5d-b38526748a50


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welcome! Thanks for opening your first pull request. We'll review it as soon as possible. Please ensure all CI checks pass and that your changes follow the project's code style.

Comment thread test/index.test.js
function cliSafe(...args) {
const { execSync: nodeExecSync } = require('node:child_process');
try {
const stdout = nodeExecSync(`${nodeBin} ${CLI} ${args.join(' ')}`, {
…ance

- Add 3-job pipeline: Security Gates (dependency review, npm audit
  --audit-level=high, dependency-tree lint), Build & Verify (lint,
  tests, rebuild normalized data, release-tag vs package.json version
  guard, tarball content inspection), Publish (npm publish --provenance)
- Pin all actions to full commit SHAs (checkout v4.4.0, setup-node
  v4.4.0, dependency-review-action v4.9.0)
- Add workflow_dispatch for manual retry; concurrency group per release
- Least-privilege permissions: contents read + id-token write only
- Add .github/dependabot.yml: weekly npm + github-actions updates
@github-actions

Copy link
Copy Markdown

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions.

@github-actions github-actions Bot added the stale label Sep 10, 2026

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 5 potential issues.

4 flags not posted on this PR by your GitHub settings β€” view them in Devin Review. (Configure)

Devin Review

Comment thread bin/cli.js

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 Export output permits arbitrary file writes

--output writes directly to any supplied path and follows symlinks. Automated or privileged callers can overwrite unrelated writable files.

(Refers to this code)

Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.


- name: Inspect package tarball contents
run: |
TARBALL=$(npm pack --dry-run --json | node -p "JSON.parse(require('fs').readFileSync(0,'utf8'))[0].filename")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ”΄ Tarball inspection blocks every release

Every release runs npm pack --dry-run, which names a tarball without creating it. The following tar command fails before publishing starts.

Learn more

The build job asks npm to simulate packing. Dry-run mode returns the prospective filename but does not write that file. The next command opens that nonexistent filename, and set -e behavior terminates the step.

Example: The command reports icon-intelligence-1.1.0.tgz. No such file exists, so tar tzf icon-intelligence-1.1.0.tgz exits nonzero and blocks the release.

Recommended fix: Run npm pack --json without --dry-run, inspect the created archive, then delete it if desired.

Suggested change
TARBALL=$(npm pack --dry-run --json | node -p "JSON.parse(require('fs').readFileSync(0,'utf8'))[0].filename")
TARBALL=$(npm pack --json | node -p "JSON.parse(require('fs').readFileSync(0,'utf8'))[0].filename")
Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.

Comment on lines +13 to +18
workflow_dispatch:
inputs:
tag:
description: "Git tag to publish (e.g. v1.1.0). Must match package.json version."
required: true
type: string

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ”΄ Manual publishing ignores requested tag

A manual run accepts tag but publishes the default branch. It can release unintended code or fail on an existing version.

Learn more

The workflow-dispatch input is metadata only unless later expressions consume it. Every checkout currently uses the workflow's default ref, and tag/version validation only runs for release events. The manual path therefore cannot fulfill its stated tag-selection contract.

Example: A maintainer enters v1.1.0 after the default branch advances to 1.2.0. All jobs check out the default branch and attempt to publish 1.2.0, not v1.1.0.

Recommended fix: Derive one requested ref from inputs.tag for manual runs and github.ref for release runs. Pass it to every checkout, fetch tags, and validate its tag against package.json for both event types before any publish step.

Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.

Comment thread scripts/normalize-data.js
svg_url: rec.svg_url || rec.image_url || '',
preview_url: rec.preview_url || rec.image_url || '',
image_url: rec.image_url || '',
local_path: localPath,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟑 Remote icons return fake local paths

Remote-only records store URLs in local_path, so getSvgPath() returns nonexistent package paths. PNG-only names return a path instead of null.

Learn more

local_path is the schema's package-relative filesystem location. The pipeline initializes it from image_url when no local path exists, leaving all remote PNG URLs and one remote SVG URL in that field. getSvgPath only checks whether the field is nonempty and then passes it to path.join.

Example: Award star add has local_path equal to https://icons.iconarchive.com/...png. getSvgPath('Award star add') returns a path resembling <package>/icons/https:/icons.iconarchive.com/...png, although no local file exists.

Recommended fix: Keep remote URLs only in svg_url, preview_url, or image_url. Set local_path to an empty string unless a package-relative file was resolved and verified, regenerate the normalized database, and test a remote-only icon explicitly.

Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.

Comment thread scripts/normalize-data.js
Comment on lines +407 to +409
const byCategory = {};
for (const rec of all) (byCategory[rec.category] = byCategory[rec.category] || []).push(rec.id);
writeJSON(path.join(outDir, 'icons-by-category.json'), byCategory);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 Category names can pollute prototypes

A raw __proto__ category mutates the derived-index accumulator instead of creating a category. Normalization can crash or generate corrupted index data.

Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.

@github-actions github-actions Bot removed the stale label Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants