Skip to content

Add publishing, lint, and type-drift gates from create-ts-lib - #11

Merged
hbmartin merged 1 commit into
mainfrom
chore/publishing-and-type-gates
Aug 7, 2026
Merged

hbmartin merged 1 commit into
mainfrom
chore/publishing-and-type-gates

Conversation

@hbmartin

@hbmartin hbmartin commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Adopts the practices from hbmartin/create-ts-lib that fit a build-less .mjs library. It deliberately does not adopt the TypeScript-source layout, a bundler, Vitest, fallow, or Semgrep — see "Not adopted" below.

Most of the diff is oxfmt reflow. Review with ?w=1 to hide it.

Publishing gates

.github/workflows/release.yml fires on a published GitHub release, not a tag push. It verifies the tag matches package.json, runs release:check, and publishes with npm trusted publishing (OIDC, id-token: write) and --provenance.

There is no NPM_TOKEN anywhere. The first release through this path needs trusted publishing configured for the package on npmjs.com (publisher: this repo, workflow release.yml). Until then the publish step fails on authentication — intended, since there's no token fallback.

prepublishOnly and release:check make the same gate runnable locally.

index.d.ts drift

This was the real gap: index.d.ts is hand-written against the .mjs sources and exports points consumers straight at src/index.mjs, so nothing verified the two agreed. Three layers now do:

  • tsconfig.json runs strict checkJs over src, bin, and index.d.ts. fonts() is annotated @param {FontsOptions} / @returns {Plugin}, so an option the implementation reads that isn't declared is a typecheck failure. noImplicitAny and useUnknownInCatchVariables are off; the rest of strict is on.
  • test/types.test.mjs imports the package by its own name — which goes through the exports map — and diffs runtime exports against those declared in index.d.ts. Verified it fails on an undeclared export.
  • publint + attw check the packed shape and ESM resolution. Both clean.

Getting from 63 type errors to 0 surfaced two real defects:

  • codemodCss's JSDoc was missing its first @param, so {object} o bound to the css parameter and every option was typed against the wrong thing.
  • A bare @import or @theme in a JSDoc description is parsed as a tag by TypeScript and silently truncates the enclosing @typedef's property list.

FontPreload is now a named export instead of being duplicated inline in the virtual:fonts declaration.

Coverage

Thresholds via Node's own runner: 66% lines / 71% branches / 59% functions. That's a ratchet just under today's numbers (68.7 / 73.6 / 61.8), not the 80% create-ts-lib uses — 80 would fail immediately, since index.mjs is at 43% and detect.mjs at 48%. The Vite hooks are covered by the fixture build rather than unit tests. Enforced on Node 22 only; V8's coverage output shifts between releases.

Node floor and CI

engines moves to >=22, @types/node is pinned to ^22 so the typecheck reflects the floor, and CI splits into:

  • checks — hermetic, matrix over Node 22/24/26: lint, typecheck, tests. Coverage, publint, attw, and pnpm audit pinned to 22.
  • integration — single version, needs network: registry staleness, fixture build, metrics, invariants.
  • notes — unchanged, now needs: [checks, integration].

Also

  • oxlint + oxfmt configured to the existing style (no semicolons, single quotes, width 100). Two lint findings were real: a useless spread in the CLI and a useless fallback in extras/server.ts.
  • Dependabot extended with npm for the root (dev tooling grouped; @types/node majors ignored so it can't drag the Node floor) and for test/fixture.
  • homepage / bugs in package.json; coverage, *.tgz, *.tsbuildinfo gitignored.
  • docs/MAINTAINERS.md gains a Checks section (including the two JSDoc traps) and a corrected release procedure.

Not adopted, deliberately

TypeScript source + a bundler (the package ships readable .mjs; a dist/ step buys little at ~1500 LOC), Vitest (node --test runs the suite in 150ms), fallow (eight flat source files, no layering to enforce), Semgrep (its ruleset targets eval/child_process; the .exec( hits here are all RegExp.exec), and JSR.

Verification

lint, typecheck, test, test:coverage, publint, types:lint all pass. 48 tests green, the fixture builds, and all six CI metric invariants still hold. I confirmed mechanically that every non-formatting diff is one of the changes described above.

verify:package fails locally because 0.1.0 is already on npm — that's the check working; it clears on the next version bump.

🤖 Generated with Claude Code


Summary by cubic

Adds release, lint, type, and coverage gates tailored for a build-less .mjs library. Enables trusted npm publishing and guards index.d.ts from drifting from the runtime code while tightening CI.

  • New Features

    • Release workflow: runs on GitHub Release, checks tag vs package.json, publishes via npm Trusted Publishing with --provenance. Local gate via prepublishOnly and release:check.
    • Type surface guards: strict checkJs over src, bin, and index.d.ts; new test/types.test.mjs compares runtime exports to index.d.ts; publint and @arethetypeswrong/cli verify the packed shape.
    • CI and coverage: split checks (Node 22/24/26 for lint, typecheck, unit tests) and integration (networked fixture/metrics). Coverage ratchet set to 66% lines / 71% branches / 59% functions on Node 22.
    • Tooling and cleanups: oxlint + oxfmt, Dependabot for root and fixture, maintainer docs. Fixed two JSDoc issues that broke types and removed minor dead code in the CLI and server.
  • Migration

    • Node floor is now >=22 (@types/node pinned to ^22).
    • Configure npm Trusted Publishing for this package (workflow release.yml). No NPM_TOKEN is used; publish will fail until trust is set.

Written for commit a5175f2. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added the exported FontPreload type for clearer TypeScript usage.
    • Added package metadata and commands for validation, coverage, packaging, and releases.
    • Automated publishing from GitHub Releases with provenance and preview-channel support.
  • Improvements

    • Raised the minimum supported Node.js version to 22.
    • Expanded automated checks across multiple Node.js versions, including linting, type checking, tests, coverage, and package validation.
    • Added consistent formatting and linting standards.
  • Documentation

    • Updated maintainer guidance for checks, CI, trusted publishing, and releases.

The package had no linter, no typechecker, no coverage floor, and nothing
standing between a local `npm publish` and the registry. This adds the gates,
adapted to a build-less .mjs library rather than adopting create-ts-lib's
TypeScript-source layout wholesale.

Publishing. `release.yml` fires on a published GitHub release, not a tag push,
checks the tag against package.json, runs the full gate, and publishes with npm
trusted publishing (OIDC) and --provenance. There is no NPM_TOKEN; the first
release needs trusted publishing configured on npmjs.com, and until then the
publish step fails on authentication, which is the intended failure mode.
`prepublishOnly` and `release:check` make that gate runnable locally.

Type drift. index.d.ts is hand-written against .mjs sources and the exports map
points consumers straight at src/index.mjs, so nothing verified the two agreed.
tsconfig.json now runs strict checkJs over src, bin and index.d.ts, with
`fonts()` annotated against its own published FontsOptions and Plugin types;
test/types.test.mjs imports the package by name (through the exports map) and
diffs runtime exports against declared ones; publint and attw check the packed
shape. Getting to zero errors surfaced two real defects: codemodCss's JSDoc was
missing its first @PARAM, so every option was typed against the wrong parameter,
and a bare @import or @theme in a JSDoc description is parsed as a tag and
silently truncates the enclosing @typedef.

Coverage thresholds are a ratchet just under today's numbers, not the 80% the
template uses -- index.mjs sits at 43% because the Vite hooks are covered by the
fixture build rather than unit tests. They are enforced on Node 22 only, since
V8's coverage output shifts between releases.

Node floor moves to 22 and CI runs 22/24/26, split into a hermetic `checks`
matrix and a single-version `integration` job for the work that needs network.

Most of the diff is oxfmt reflow; `git diff -w` shows the substance. Two lint
findings were real (a useless spread in the CLI, a useless fallback in
extras/server.ts). Behaviour is unchanged: 48 tests pass, the fixture builds,
and all six CI metric invariants still hold.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​types/​node@​22.20.11001008195100
Addedpublint@​0.3.231001008192100
Addedoxfmt@​0.62.0861008896100
Added@​arethetypeswrong/​cli@​0.18.59910010087100
Addedtypescript@​7.0.29910089100100
Addedoxlint@​1.77.0991009196100

View full report

@socket-security

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm highlight.js is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/@arethetypeswrong/cli@0.18.5npm/highlight.js@10.7.3

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/highlight.js@10.7.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request adds strict JavaScript type checking, a shared FontPreload declaration, and type-surface tests. It expands package scripts and configures Oxfmt, Oxlint, Dependabot, and multi-Node CI checks. A GitHub Release workflow now validates tags and publishes npm packages with provenance. Existing source, harness, and test files receive formatting and JSDoc updates. One CSS import condition now requires both import-related options.

Sequence Diagram(s)

sequenceDiagram
  participant GitHubRelease
  participant ReleaseWorkflow
  participant Npm
  GitHubRelease->>ReleaseWorkflow: publish release event
  ReleaseWorkflow->>ReleaseWorkflow: validate tag and run checks
  ReleaseWorkflow->>Npm: publish with provenance and dist-tag
Loading

Possibly related PRs

  • hbmartin/tailwind-vite-font-kit#2 — Modifies overlapping CI, Dependabot, and core source areas, but addresses different plugin and font-processing functionality.
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main publishing, linting, and type-drift changes in the pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/publishing-and-type-gates

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Line 48: Update the release workflow command assigning tag to avoid
interpolating github.event.release.tag_name directly into shell source; pass the
release tag through the step or job env and read it from an environment variable
inside the shell script, preserving the existing tag value used by the publish
flow.
- Around line 32-41: Pin the release workflow toolchain by changing node-version
from 22 to 22.14.0 and replacing npm@latest in the Upgrade npm step with
npm@11.5.1. Keep the existing npm installation and PATH setup unchanged.
- Line 33: Remove the explicit cache: pnpm setting from the publishing job in
the release workflow, leaving package-manager-cache: false intact so the release
path neither restores nor saves the pnpm store.

In `@docs/MAINTAINERS.md`:
- Line 31: Update the documentation comment for the `pnpm run check` command in
MAINTAINERS.md to describe it as the local lint → typecheck → coverage gate,
removing the claim that it represents all CI work and runs on every Node
version.

In `@tsconfig.json`:
- Line 12: Update the tsconfig.json compiler option skipLibCheck from true to
false, or remove it, so pnpm run typecheck validates index.d.ts and other
included declaration files.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 74d2928a-6029-49de-bf23-f1a9fb570519

📥 Commits

Reviewing files that changed from the base of the PR and between 9a09d11 and a5175f2.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (29)
  • .github/dependabot.yml
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • .gitignore
  • .oxfmtrc.json
  • .oxlintrc.json
  • bin/tss-fonts.mjs
  • docs/MAINTAINERS.md
  • extras/opsz-policy.mjs
  • extras/server.ts
  • harness/clswidth.mjs
  • harness/sweep.mjs
  • harness/targets.mjs
  • harness/waterfall.mjs
  • index.d.ts
  • package.json
  • src/codemod-css.mjs
  • src/detect.mjs
  • src/diff.mjs
  • src/generate.mjs
  • src/index.mjs
  • src/metrics.mjs
  • src/opsz.mjs
  • test/detect.test.mjs
  • test/metrics.test.mjs
  • test/opsz.test.mjs
  • test/types.test.mjs
  • test/vite-codemod.test.mjs
  • tsconfig.json

Comment on lines +32 to +41
node-version: 22
cache: pnpm
registry-url: https://registry.npmjs.org

# Node 22 ships npm 10, which predates trusted publishing.
- name: Upgrade npm
run: |
npm config set prefix ~/.local
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
PATH="$HOME/.local/bin:$PATH" npm install -g npm@latest

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- workflow ---'
cat -n .github/workflows/release.yml | sed -n '1,90p'

printf '%s\n' '--- repository toolchain declarations ---'
rg -n --hidden -S 'node-version|npm@|packageManager|engines|trusted|provenance|npm publish|actions/setup-node' \
  .github package.json pnpm-lock.yaml 2>/dev/null || true

printf '%s\n' '--- local npm/node availability ---'
node --version 2>/dev/null || true
npm --version 2>/dev/null || true

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 12923


🌐 Web query:

npm trusted publishing requirements npm 11.5.1 Node 22.14.0 official documentation

💡 Result:

Trusted publishing in npm allows you to publish packages directly from CI/CD workflows using OpenID Connect (OIDC) authentication, removing the requirement for long-lived npm access tokens [1][2]. As of the specified versions (npm 11.5.1 and Node.js 22.14.0), the requirements and details for using trusted publishing are: Core Version Requirements - npm CLI: Version 11.5.1 or later [1][2]. - Node.js: Version 22.14.0 or higher [1][2]. General Prerequisites - Existing Package: The npm package must already exist on the registry before a trusted publisher can be configured for it [3][4]. - Permissions: You must have write access (maintainer or owner) to the package [3][4]. - Account Security: Two-factor authentication (2FA) must be enabled at the npm account level [3][5]. - CI/CD Provider: You must use a supported cloud-based CI/CD provider (such as GitHub Actions, GitLab CI/CD, or CircleCI) with cloud-hosted runners [1][6][4]. Self-hosted runners are not supported [1]. Configuration and Usage - OIDC Authentication: Trusted publishing works by exchanging a short-lived OIDC token for an npm publish token at runtime [4][2]. - Provenance: When using trusted publishing, provenance attestations are automatically generated for your packages without requiring the --provenance flag [6]. - Command Flags: When configuring trust relationships, you must specify at least one permission flag: --allow-publish or --allow-stage-publish [3][5]. - Important Note: If you encounter an ENEEDAUTH error, ensure that all fields in your configuration (such as workflow filenames and IDs) are exact and case-sensitive [1]. Additionally, for GitHub Actions, verify that the id-token: write permission is set in your workflow file [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- package metadata ---'
cat -n package.json | sed -n '18,75p'

printf '%s\n' '--- npm 11.5.1 metadata ---'
curl -fsSL https://registry.npmjs.org/npm/11.5.1 |
  jq '{version, engines, dist: {tarball, integrity}}'

printf '%s\n' '--- npm latest metadata ---'
curl -fsSL https://registry.npmjs.org/npm/latest |
  jq '{version, engines}'

printf '%s\n' '--- setup-node version-resolution documentation references ---'
rg -n -S 'node-version: 22|22\.14\.0|semver|latest|check-latest' .github README.md package.json 2>/dev/null || true

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 3800


Pin the npm trusted-publishing toolchain.

Set node-version to 22.14.0 and install npm@11.5.1 instead of npm@latest. Both current version selectors can change independently and can alter or break the release workflow.

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 41-41: ad-hoc installation of packages (adhoc-packages): installs a package outside of a lockfile

(adhoc-packages)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 32 - 41, Pin the release workflow
toolchain by changing node-version from 22 to 22.14.0 and replacing npm@latest
in the Upgrade npm step with npm@11.5.1. Keep the existing npm installation and
PATH setup unchanged.

Source: Linters/SAST tools

- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
cache: pnpm

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu
printf '%s\n' '--- workflow files ---'
git ls-files '.github/workflows/release.yml'
printf '%s\n' '--- release workflow ---'
cat -n .github/workflows/release.yml

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 3052


🌐 Web query:

npm trusted publishing package manager caching release builds setup-node cache pnpm guidance

💡 Result:

To set up npm trusted publishing with dependency caching in your CI/CD workflows, follow this guidance based on current best practices for August 2026. Trusted Publishing Overview Trusted publishing replaces long-lived NPM_TOKEN secrets with short-lived OpenID Connect (OIDC) tokens [1][2]. You must configure the trust relationship on npmjs.com under your package settings, specifying your CI provider, repository, and workflow constraints [3][2]. Your CI job requires id-token: write permissions [4][5][2]. When configured, the npm CLI automatically detects the environment and uses OIDC to authenticate, removing the need for an explicit authentication token [1][2]. Caching Guidance For release builds, it is common practice to disable automatic package manager caching to ensure the environment is clean and reproducible [4][5]. However, for general CI jobs or if you choose to cache dependencies for speed, note the following configurations: 1. Using setup-node with pnpm: The actions/setup-node action supports caching the pnpm store [6][7]. To implement this, set cache: 'pnpm' in your setup-node configuration [8][7]. Ensure your workflow defines cache-dependency-path: pnpm-lock.yaml to target the correct lockfile [7]. Example Configuration: - uses: actions/setup-node@v7 with: node-version: '24' cache: 'pnpm' cache-dependency-path: pnpm-lock.yaml - run: pnpm install --frozen-lockfile 2. Important Caching Considerations: - Caching for Release Builds: Official documentation often recommends setting package-manager-cache: false during the publish job to ensure build isolation [4][5]. - pnpm and setup-node: Always ensure pnpm is available (e.g., via corepack or pnpm/action-setup) before the setup-node step, as setup-node may fail if it cannot locate the pnpm executable [8][6][9]. - Cache Contents: Using cache: 'pnpm' caches the pnpm store, not the node_modules directory [6][7]. Running pnpm install --frozen-lockfile is still necessary to reconstruct the project layout and validate dependencies against the lockfile [7]. Provenance Trusted publishing automatically generates provenance attestations for your packages [4][10]. If you encounter issues, verify your npm CLI version (v11.15.0 or later is recommended) [1][10]. While automatic in many cases, you can explicitly ensure provenance by adding --provenance to your publish command or setting "provenance": true in your package.json under publishConfig [4][10].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu
python3 - <<'PY'
from urllib.request import urlopen
from html import unescape
import re

url = "https://docs.npmjs.com/trusted-publishers/"
try:
    text = urlopen(url, timeout=15).read().decode("utf-8", "replace")
except Exception as exc:
    print(f"fetch failed: {exc}")
    raise SystemExit(0)

text = re.sub(r"<script\b[^>]*>.*?</script>", " ", text, flags=re.I|re.S)
text = re.sub(r"<style\b[^>]*>.*?</style>", " ", text, flags=re.I|re.S)
text = re.sub(r"<[^>]+>", " ", text)
text = re.sub(r"\s+", " ", unescape(text))
for term in ("cache", "cach", "package-manager-cache", "release build", "npm 11"):
    print(f"--- {term} ---")
    for m in re.finditer(term, text, flags=re.I):
        print(text[max(0, m.start()-250):m.end()+350])
PY

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 318


🏁 Script executed:

#!/bin/bash
set -eu
curl -k -L --max-time 20 -sS https://docs.npmjs.com/trusted-publishers/ |
  python3 -c 'import sys,re,html; s=sys.stdin.read(); s=re.sub(r"<script\b[^>]*>.*?</script>"," ",s,flags=re.I|re.S); s=re.sub(r"<style\b[^>]*>.*?</style>"," ",s,flags=re.I|re.S); s=re.sub(r"<[^>]+>"," ",s); s=re.sub(r"\s+"," ",html.unescape(s)); terms=("cache","package-manager-cache","release build","publishing workflow"); [(print(f"--- {t} ---\n"+s[max(0,m.start()-300):m.end()+500])) for t in terms for m in list(re.finditer(t,s,re.I))[:10]]'

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 6005


🏁 Script executed:

#!/bin/bash
set -eu
curl -k -L --max-time 20 -sS https://raw.githubusercontent.com/actions/setup-node/main/action.yml |
  sed -n '1,180p'
printf '%s\n' '--- setup-node cache documentation ---'
curl -k -L --max-time 20 -sS https://raw.githubusercontent.com/actions/setup-node/main/docs/advanced-usage.md |
  rg -n -C 4 'package-manager-cache|cache:.*pnpm|cache' | head -120

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 8157


🏁 Script executed:

#!/bin/bash
set -eu
for url in \
  https://raw.githubusercontent.com/actions/setup-node/main/src/main.ts \
  https://raw.githubusercontent.com/actions/setup-node/main/src/cache-restore.ts \
  https://raw.githubusercontent.com/actions/setup-node/main/src/cache-save.ts
do
  printf '%s\n' "--- $url ---"
  curl -k -L --max-time 20 -sS "$url" | rg -n -C 5 'packageManagerCache|cache|restoreCache|saveCache' | head -100
done

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 8002


Remove cache: pnpm from the publishing job.

package-manager-cache: false does not disable an explicitly configured cache input. The job must not restore or save the pnpm store in this release path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 33, Remove the explicit cache: pnpm
setting from the publishing job in the release workflow, leaving
package-manager-cache: false intact so the release path neither restores nor
saves the pnpm store.

Source: Linters/SAST tools


- name: Tag matches package.json version
run: |
tag="${{ github.event.release.tag_name }}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not interpolate the release tag into shell source.

GitHub expands this expression before the shell parses the script. A release tag containing shell metacharacters can alter the command in this OIDC-enabled publish job. Pass the value through env and read the environment variable.

Proposed fix
       - name: Tag matches package.json version
+        env:
+          RELEASE_TAG: ${{ github.event.release.tag_name }}
         run: |
-          tag="${{ github.event.release.tag_name }}"
+          tag="$RELEASE_TAG"
           pkg="v$(node -p "require('./package.json').version")"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tag="${{ github.event.release.tag_name }}"
- name: Tag matches package.json version
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
tag="$RELEASE_TAG"
pkg="v$(node -p "require('./package.json').version")"
🧰 Tools
🪛 zizmor (1.29.0)

[error] 48-48: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 48, Update the release workflow
command assigning tag to avoid interpolating github.event.release.tag_name
directly into shell source; pass the release tag through the step or job env and
read it from an environment variable inside the shell script, preserving the
existing tag value used by the publish flow.

Source: Linters/SAST tools

Comment thread docs/MAINTAINERS.md
```bash
pnpm install
pnpm test # unit tests, no network, ~150 ms
pnpm run check # everything CI runs on every Node version, in CI's order

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the check description.

check runs lint, typecheck, and coverage only. It does not run all CI work, and coverage is documented as Node-22-only. Describe it as the local lint → typecheck → coverage gate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/MAINTAINERS.md` at line 31, Update the documentation comment for the
`pnpm run check` command in MAINTAINERS.md to describe it as the local lint →
typecheck → coverage gate, removing the claim that it represents all CI work and
runs on every Node version.

Comment thread tsconfig.json
"allowJs": true,
"checkJs": true,
"noEmit": true,
"skipLibCheck": true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
set -eu

# Confirm that the public declaration file is included while declaration checks are enabled.
sed -n '1,28p' tsconfig.json
rg -n '^(export|declare module)' index.d.ts

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 974


🏁 Script executed:

#!/bin/sh
set -eu

printf '%s\n' '--- tsconfig.json ---'
cat -n tsconfig.json

printf '%s\n' '--- index.d.ts ---'
cat -n index.d.ts

printf '%s\n' '--- package scripts and typecheck references ---'
node - <<'JS'
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('package.json', 'utf8'));
console.log(JSON.stringify({scripts: p.scripts, types: p.types, files: p.files}, null, 2));
JS
rg -n 'typecheck|tsc|skipLibCheck|index\.d\.ts' --glob '!package-lock.json' --glob '!pnpm-lock.yaml' --glob '!yarn.lock' .

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 9099


🏁 Script executed:

#!/bin/sh
set -eu

printf '%s\n' '--- compiler availability ---'
command -v tsc || true
tsc --version 2>/dev/null || true

printf '%s\n' '--- type-surface test ---'
cat -n test/types.test.mjs

printf '%s\n' '--- maintainer typecheck documentation ---'
sed -n '55,73p' docs/MAINTAINERS.md

printf '%s\n' '--- temporary skipLibCheck probe ---'
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT

cat > "$tmpdir/index.d.ts" <<'EOF'
export interface PublicOptions {
  value: MissingType
}
EOF

cat > "$tmpdir/use.ts" <<'EOF'
import type { PublicOptions } from "./index.js"
const options: PublicOptions = { value: 1 }
EOF

for setting in true false; do
  cat > "$tmpdir/tsconfig.json" <<EOF
{
  "compilerOptions": {
    "strict": true,
    "skipLibCheck": $setting,
    "noEmit": true
  },
  "include": ["index.d.ts", "use.ts"]
}
EOF
  echo "skipLibCheck=$setting"
  if tsc -p "$tmpdir/tsconfig.json" --pretty false > "$tmpdir/out-$setting.txt" 2>&1; then
    echo "status=0"
  else
    echo "status=$?"
  fi
  cat "$tmpdir/out-$setting.txt"
done

Repository: hbmartin/tailwind-vite-font-kit

Length of output: 4535


Enable checking for index.d.ts.

skipLibCheck suppresses semantic errors in the included public declaration file. Remove this setting or set it to false so pnpm run typecheck validates the published API declarations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tsconfig.json` at line 12, Update the tsconfig.json compiler option
skipLibCheck from true to false, or remove it, so pnpm run typecheck validates
index.d.ts and other included declaration files.

@hbmartin
hbmartin merged commit bdb104f into main Aug 7, 2026
11 of 12 checks passed
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.

1 participant