Skip to content

chore: replace ESLint with Biome and update GitHub Actions#474

Merged
Jamie-BitFlight merged 32 commits intomainfrom
claude/update-actions-biome-uXcwR
Feb 4, 2026
Merged

chore: replace ESLint with Biome and update GitHub Actions#474
Jamie-BitFlight merged 32 commits intomainfrom
claude/update-actions-biome-uXcwR

Conversation

@Jamie-BitFlight
Copy link
Contributor

@Jamie-BitFlight Jamie-BitFlight commented Feb 3, 2026

  • Replace ESLint with Biome for linting and formatting
  • Update local setup-node action from v4 to v6
  • Update CI linting workflow to use reviewdog-action-biome
  • Remove 19 ESLint-related dependencies (~397 packages)
  • Add biome.json configuration migrated from Prettier settings
  • Update lint-staged to use Biome for TypeScript files
  • Apply Biome auto-fixes for import type suggestions
  • Keep Prettier as runtime dependency (used by app itself)

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP

Summary by CodeRabbit

  • Documentation

    • Added many new agent/skill guides, linting and architecture references, project config, policies, and a code-smells TODO to standardize workflows.
  • Build & Tooling

    • Migrated linting/formatting to Biome, added format/check scripts, updated Node engine hints, and CI/workflows to run Biome checks.
  • Improvements

    • Strengthened typings and runtime validation, refined logging/formatting behavior, adjusted editor/Prettier settings, and removed legacy ESLint config.
  • Tests

    • Updated test scaffolding/path handling and added extensive integration tests for auto-detection and external-repo scenarios.

claude added 10 commits February 3, 2026 09:14
- Replace ESLint with Biome for linting and formatting
- Update local setup-node action from v4 to v6
- Update CI linting workflow to use reviewdog-action-biome
- Remove 19 ESLint-related dependencies (~397 packages)
- Add biome.json configuration migrated from Prettier settings
- Update lint-staged to use Biome for TypeScript files
- Apply Biome auto-fixes for import type suggestions
- Keep Prettier as runtime dependency (used by app itself)

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
- Configure Biome with strict linting rules for all rule groups
- Enable performance, security, complexity, correctness checks
- Add naming convention rules for variables, functions, properties
- Add biomejs/setup-biome@v2 to CI workflows
- Update test.yml to run biome check before tests
- Update push_code_linting.yml with explicit Biome setup step

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Adds project-specific context:
- TypeScript 5.7.3, Node.js 20.x, ESM/CJS dual output
- Security threat model (path traversal, command injection, YAML parsing, ReDoS)
- Biome linting alignment and tolerances
- Section updater pattern verification
- GitHub Action error handling patterns

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Changes:
- Enable strict Biome rules (noForEach, useLiteralKeys, noConsole,
  noParameterAssign, useDefaultParameterLast, useNodejsImportProtocol)
- Replace `any` types with `unknown` throughout codebase
- Add explicit type annotations to all exported functions/variables
- Fix async functions to use await or remove async keyword
- Add biome-ignore comments for ESM polyfill patterns (__filename/__dirname)
- Relax test file rules appropriately (useAwait, noMisplacedAssertion, etc.)
- Fix .editorconfig invalid 'ignore' values
- Update code-review agent with accurate Biome rules documentation
- Add Claude skills (agent-creator, claude-skills-overview-2026)
- Customize holistic-linting for TypeScript/Biome project

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
@github-actions
Copy link
Contributor

github-actions bot commented Feb 3, 2026

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 81.02% 726 / 896
🔵 Statements 81.08% 733 / 904
🔵 Functions 83.33% 95 / 114
🔵 Branches 74.02% 342 / 462
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/Action.ts 92.85% 87.5% 100% 92.85% 141, 212, 239
src/constants.ts 100% 100% 100% 100%
src/helpers.ts 87.19% 74.25% 88.23% 87.19% 122, 131, 246-248, 288-305, 315, 329, 341, 389-393, 424, 457-458
src/inputs.ts 90.65% 86.76% 100% 90.65% 328-333, 362-363, 391, 486, 621-626
src/prettier.ts 92.85% 88.88% 100% 92.3% 73
src/readme-editor.ts 88.88% 76.19% 100% 88.88% 50-51, 80-81
src/readme-generator.ts 100% 100% 100% 100%
src/save.ts 0% 0% 0% 0% 17-23
src/svg-editor.mts 0% 0% 0% 0% 46-183
src/logtask/index.ts 96.8% 90.54% 100% 96.77% 114-117
src/sections/index.ts 80% 84.61% 100% 80% 32, 60-61
src/sections/update-badges.ts 42.3% 25% 25% 42.3% 25-79, 95-97
src/sections/update-branding.ts 58.97% 42.1% 75% 58.97% 39-40, 57, 64-72, 89-90, 99-106, 137
src/sections/update-contents.ts 100% 93.75% 100% 100%
src/sections/update-description.ts 100% 50% 100% 100%
src/sections/update-inputs.ts 96.66% 72.22% 100% 96.66% 46
src/sections/update-outputs.ts 96.77% 62.5% 100% 96.77% 44
src/sections/update-title.ts 94.44% 50% 100% 94.44% 28
src/sections/update-usage.ts 100% 80% 100% 100%
Generated in workflow #439 for commit 13f2431 by the Vitest Coverage Report Action

@coderabbitai
Copy link

coderabbitai bot commented Feb 3, 2026

Walkthrough

Adds many new agent/skill documentation files, migrates linting/formatting from ESLint/Babel to Biome (configs, scripts, CI), converts numerous runtime imports to type-only imports, strengthens typings and runtime guards, updates test environment/path handling, enhances repository/version detection, adds large integration tests, and removes the ESLint config.

Changes

Cohort / File(s) Summary
Agent & Reviewer Docs
.claude/agents/code-review.md, .claude/agents/context-gathering.md, .claude/agents/linting-root-cause-resolver.md, .claude/agents/post-linting-architecture-reviewer.md
New documentation defining agent workflows, checklists, threat models, artifact formats, and review processes (documentation-only).
Skills, Templates & References
.claude/skills/agent-creator/SKILL.md, .claude/skills/agent-creator/references/*, .claude/skills/claude-skills-overview-2026/SKILL.md, .claude/skills/holistic-linting/*, .claude/skills/delegate/SKILL.md
Extensive new SKILL.md and reference docs (agent templates, frontmatter schema, examples, SOPs). Doc-only additions.
Linting & Formatter Migration
eslint.config.mjs, biome.json, .prettierrc.cjs, .editorconfig, package.json
Removed ESLint config and many ESLint/Babel devDeps; added comprehensive biome.json, adjusted Prettier/EditorConfig, updated npm scripts to Biome-based tooling and updated Node engine constraint.
CI / GitHub Actions
.github/workflows/push_code_linting.yml, .github/workflows/test.yml, .github/workflows/integration-test.yml, .github/actions/setup-node/action.yml
Inserted Biome setup/check and reviewdog-biome steps, bumped actions/setup-node usage to v6, expanded workflow permissions, added README auto-detection/validation and stricter integration-test checks.
Type-only Imports & Test Updates
src/*, src/sections/*, src/readme-generator.ts, src/save.ts, __tests__/*
Converted many runtime imports to import type, replaced __dirname/__filename uses with import.meta.dirname, and changed env cleanup to assignments of undefined in tests.
Typing, Guards & Signatures
src/helpers.ts, src/inputs.ts, src/prettier.ts, src/constants.ts, src/logtask/index.ts, src/Action.ts
Added explicit type annotations, hardened runtime guards (unknown vs any), adjusted function signatures and enums, improved repository/version detection and logging helpers.
API / Behavioral Signature Changes
src/Action.ts, src/svg-editor.mts, src/sections/update-branding.ts
Action.validate now accepts unknown; several SVGEditor methods changed from async→sync; generateImgMarkup width param explicitly typed as string.
Logging & Formatting Helpers
src/logtask/index.ts, src/prettier.ts, src/readme-editor.ts
Refactored logging helpers with explicit types, ensured Prettier format calls await results and accept filepath options; mostly typing and minor signature formatting changes.
New Tests: Integration External Repo
__tests__/integration-external-repo.test.ts
Large new integration test suite validating owner/repo/version auto-detection across .git/config, package.json, env inputs, and README usage lines.
Misc docs / housekeeping
.claude/CLAUDE.md, .claude/smells-todo.md, .claude/skills/*
Additional project docs (config, technical debt checklist) and other skill documentation (doc-only).

Sequence Diagram(s)

sequenceDiagram
  participant GH as GitHub Actions Runner
  participant WF as Integration Workflow
  participant Action as Auto-Detection Logic
  participant Git as Target Repo (.git/config)
  participant PKG as Target package.json
  participant README as README.md

  GH->>WF: start integration job (matrix.repo)
  WF->>Action: run auto-detection & validation
  Action->>Git: read/parse .git/config for owner/repo
  Action->>PKG: read package.json for version
  Action->>README: parse usage line (uses: owner/repo@version)
  Action->>Action: compare detected values to expected matrix
  Action-->>WF: return detection results (PASS/FAIL)
  WF-->>GH: emit success or fail based on validation
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

dependencies, automated

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: replacing ESLint with Biome and updating GitHub Actions. It directly reflects the primary modifications in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/update-actions-biome-uXcwR

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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
package.json (1)

190-193: ⚠️ Potential issue | 🟠 Major

Narrow engines.node to strict Node 20.x requirement.

The current range >=20.0.0 <26.0.0 allows Node 21–25, which violates the project standard. The volta configuration (.node-version) and coding guidelines both specify Node 20.x only. Update to >=20.0.0 <21.0.0.

Suggested fix
  "engines": {
-    "node": ">=20.0.0 <26.0.0",
+    "node": ">=20.0.0 <21.0.0",
     "npm": ">=10.0.0"
  },
🤖 Fix all issues with AI agents
In `@__tests__/action.test.ts`:
- Around line 26-28: Replace the manual environment mutation and restoration
pattern (setting process.env.GITHUB_REPOSITORY, process.env.INPUT_OWNER,
process.env.INPUT_REPO to undefined and toggling process.env = tempEnv) with
Vitest's vi.stubEnv() API: use vi.stubEnv() to clear or set those keys for the
test and rely on the returned stub to restore afterwards; update the test setup
to call vi.stubEnv({ GITHUB_REPOSITORY: undefined, INPUT_OWNER: undefined,
INPUT_REPO: undefined }) (or set only needed keys) and call stub.restore() in
teardown or let Vitest auto-restore, ensuring consistent environment handling
with vi.stubEnv() instead of assigning process.env directly.

In `@__tests__/helpers.test.ts`:
- Around line 41-45: The test resets like "process.env.GITHUB_REPOSITORY =
undefined; process.env.INPUT_OWNER = undefined; process.env.INPUT_REPO =
undefined; process.env.INPUT_README = undefined; process.env.INPUT_ACTION =
undefined;" should be changed to actually unset the env vars (use delete
process.env.GITHUB_REPOSITORY; delete process.env.INPUT_OWNER; delete
process.env.INPUT_REPO; delete process.env.INPUT_README; delete
process.env.INPUT_ACTION;) or, better, manage test envs with Vitest helpers
(vi.stubEnv()/vi.unstubAllEnvs()) in your setup/teardown so the variables are
truly removed (apply the same replacement for the other occurrences of
process.env assignments like the ones later for INPUT_* variables).

In `@__tests__/inputs.test.ts`:
- Around line 161-175: The test is not properly isolating environment variables:
replace direct assignments to process.env.INPUT_USER and process.env.INPUT_REPO
with vi.stubEnv calls that explicitly stub/clear INPUT_OWNER and INPUT_REPO (and
any other inputs used by loadDefaultConfig) so the test for loadDefaultConfig
(tests named "loadDefaultConfig from github context GITHUB_REPOSITORY env var"
and "loadDefaultConfig from provided context payload") uses
vi.stubEnv('INPUT_OWNER', '') and vi.stubEnv('INPUT_REPO', '') (and
vi.stubEnv('GITHUB_REPOSITORY', '') where needed) instead of setting unrelated
INPUT_USER or mutating process.env directly to ensure proper test isolation.

In @.claude/skills/agent-creator/references/agent-templates.md:
- Around line 144-156: Update the agent-templates.md table row for the `hooks`
field to mark it as a valid agent frontmatter field (type: object, default:
(none)) and replace the "NOT VALID IN AGENT FRONTMATTER" note with a concise
description like "Lifecycle hook configurations scoped to individual agents (see
agent-schema.md for supported hook keys)"; ensure the `hooks` row matches the
specification in agent-schema.md and SKILL.md so the table shows the correct
type and description for `hooks`.

In @.claude/skills/holistic-linting/PROJECT-CONFIG.md:
- Around line 5-8: Update the "Linter: Biome 2.x (replaces ESLint + Prettier)"
line in PROJECT-CONFIG.md to clarify scope: change it to state that Biome 2.x is
the primary linter/formatter for TypeScript/JavaScript only, and explicitly note
that Prettier remains a runtime dependency used for Markdown/YAML formatting and
for non-JS files via lint-staged; edit the existing "Linter: Biome 2.x (replaces
ESLint + Prettier)" text to this clarified phrasing so readers understand Biome
does not fully replace Prettier.

In @.claude/skills/holistic-linting/SKILL.md:
- Around line 275-344: Update the JS/TS tooling references to Biome: replace
mentions of "ESLint" and "Prettier" in the detection table with "Biome (JS/TS)"
and mention presence of biome.json and dependency `@biomejs/biome` as detection
signals; then replace the example commands under "For JavaScript/TypeScript
files" to show using Biome (e.g., use "biome format" to format and "biome check"
to lint/check) instead of npx prettier/npx eslint, and ensure any guidance about
ordering (format then lint) and using --files/staged patterns remains the same.

In @.github/workflows/push_code_linting.yml:
- Around line 46-49: Remove the unsupported "type: string" input property from
the action metadata in .github/actions/setup-node/action.yml (the input defined
for the custom action used by the setup-node step), leaving only supported input
keys (description, required, default, deprecationMessage); locate the input
block that contains "type: string" (used by the setup-node action referenced in
the workflow) and delete that line so actionlint validation passes.

In @.github/workflows/test.yml:
- Around line 54-62: Remove the hard-coded "version: latest" parameter from the
Biome setup step that uses biomejs/setup-biome@v2 in the GitHub Actions
workflow; edit the "Setup Biome" step to drop the "version: latest" line so the
action auto-detects the version from your lockfile (ensure `@biomejs/biome` is
pinned in package-lock.json/yarn.lock for deterministic runs).

In `@package.json`:
- Around line 61-73: The package.json scripts declare Biome-based
formatting/linting (scripts like "format", "format:check", "lint:biome",
"lint:biome:fix") and the engines.node range allows >=20.0.0 <26.0.0, which
conflicts with project docs that expect ESLint+Prettier and Node 20.x; either
(A) update docs to reflect Biome and the relaxed engines.node range OR (B)
restore ESLint/Prettier tooling and tighten engines.node to <21.0.0: if choosing
B, add back an ESLint config (.eslintrc.cjs), switch package.json scripts to use
eslint and prettier (replace "lint:biome"/"format" with "lint"/"format" commands
that invoke eslint and prettier), update lint-staged if present to run eslint
--fix/prettier --write for TS/JSON, and change the engines.node entry to
">=20.0.0 <21.0.0"; if choosing A, update .github/copilot-instructions.md to
document Biome as the standard and optionally keep engines.node as-is.

In `@src/Action.ts`:
- Around line 76-84: The Steps type currently requires an env property which is
optional in GitHub Actions composite steps; update the Steps type definition by
making env optional (change env: { [key: string]: string } to env?: { [key:
string]: string }) and adjust any code that assumes env is always present to
handle undefined (e.g., checks in functions that read Steps.env). This touches
the Steps type declaration in Action.ts and any consumers that iterate or spread
step.env should guard for undefined.

In `@src/svg-editor.mts`:
- Around line 70-74: Update the JSDoc for generateSvgImage so the `@returns` tag
matches the implementation: change the documented return type from Promise<void>
to void in the JSDoc above the generateSvgImage method; ensure the JSDoc now
reads `@returns` {void} and remove any mention of async/Promise semantics to avoid
confusion for callers and maintainers.
🧹 Nitpick comments (3)
src/Action.ts (1)

125-141: Type predicate should narrow to ActionYaml, not ActionType.

The guard checks name, description, and runs, which matches ActionYaml. Returning obj is ActionType makes the predicate unsound and can mislead TypeScript narrowing.

🔧 Suggested fix
-  static validate(obj: unknown): obj is ActionType {
+  static validate(obj: unknown): obj is ActionYaml {
     if (typeof obj !== 'object' || obj === null) {
       return false;
     }
     const record = obj as Record<string, unknown>;
-    if ('name' in record && 'description' in record && 'runs' in record) {
-      const runs = record.runs as Record<string, unknown> | undefined;
-      if (runs && 'using' in runs) {
-        return (
-          typeof record.name === 'string' &&
-          typeof record.description === 'string' &&
-          typeof runs.using === 'string'
-        );
-      }
-    }
-    return false;
+    if (!('name' in record) || !('description' in record) || !('runs' in record)) {
+      return false;
+    }
+    const runs = record.runs as Record<string, unknown> | undefined;
+    return (
+      typeof record.name === 'string' &&
+      typeof record.description === 'string' &&
+      !!runs &&
+      typeof runs.using === 'string'
+    );
   }
src/logtask/index.ts (1)

32-72: Consider removing unused failed return value.

The highlightMessage function returns { desc, failed }, but the caller at line 211 only destructures desc. The failed property is computed but never used.

♻️ Simplify return type if `failed` is not needed
-function highlightMessage(step: string, message: string): { desc: string; failed: boolean } {
-  let failed = false;
+function highlightMessage(step: string, message: string): string {
   const ci = inGitHubActions();
   let desc: string;
   switch (step) {
     // ... cases remain the same, just remove `failed = true` assignments
     case 'FAILURE': {
       desc = ci ? message : yellow.bold(`${message}`);
-      failed = true;
       break;
     }
     // ...
   }
-  return { desc, failed };
+  return desc;
 }
src/sections/index.ts (1)

36-57: Consider removing await from synchronous updater returns.

Some updaters (updateBranding, updateBadges, updateInputs, updateOutputs, updateContents) return synchronous Record<string, string>, while others (updateUsage, updateTitle, updateDescription) return Promise<Record<string, string>>.

Using return await on synchronous functions is harmless but unnecessary. The current approach does provide consistency across all cases, which aids maintainability. If consistency is the goal, this is acceptable; otherwise, await could be removed from the synchronous cases.

Comment on lines +41 to +45
process.env.GITHUB_REPOSITORY = undefined;
process.env.INPUT_OWNER = undefined;
process.env.INPUT_REPO = undefined;
process.env.INPUT_README = undefined;
process.env.INPUT_ACTION = undefined;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Node.js process.env assignment undefined behavior

💡 Result:

In Node.js, process.env is a special object that represents environment variables, and any assignment to a key is coerced to a string. So:

process.env.FOO = undefined;
console.log(process.env.FOO); // 'undefined' (a string)

This often looks like “undefined behavior”, but it’s intentional: setting to undefined does not remove the variable—it stores the literal string "undefined". Node’s docs explicitly show this and note the implicit string conversion is deprecated, and future Node versions may throw if you assign a non string/number/boolean value. [1]

To actually unset an environment variable in the current process, use delete:

delete process.env.FOO;
console.log(process.env.FOO); // undefined (missing key)

[1] (nodejs.org)

Citations:


🏁 Script executed:

#!/bin/bash
# Examine the test file to understand context
head -80 __tests__/helpers.test.ts | tail -45

Repository: bitflight-devops/github-action-readme-generator

Length of output: 1696


Replace process.env.X = undefined with delete process.env.X; undefined assignment stores the string "undefined", not an unset variable.

In Node.js, assigning undefined to an environment variable does not remove it—it stores the literal string "undefined", which can cause tests to behave unexpectedly if they check for variable presence. Use delete to properly unset, or preferably use Vitest's vi.stubEnv() / vi.unstubAllEnvs() for cleaner test env management.

🔧 Suggested fixes
-    process.env.GITHUB_REPOSITORY = undefined;
-    process.env.INPUT_OWNER = undefined;
-    process.env.INPUT_REPO = undefined;
-    process.env.INPUT_README = undefined;
-    process.env.INPUT_ACTION = undefined;
+    delete process.env.GITHUB_REPOSITORY;
+    delete process.env.INPUT_OWNER;
+    delete process.env.INPUT_REPO;
+    delete process.env.INPUT_README;
+    delete process.env.INPUT_ACTION;
-    process.env.GITHUB_REPOSITORY = undefined;
-    process.env.INPUT_OWNER = undefined;
-    process.env.INPUT_REPO = undefined;
+    delete process.env.GITHUB_REPOSITORY;
+    delete process.env.INPUT_OWNER;
+    delete process.env.INPUT_REPO;

Also applies to: 71-73

🤖 Prompt for AI Agents
In `@__tests__/helpers.test.ts` around lines 41 - 45, The test resets like
"process.env.GITHUB_REPOSITORY = undefined; process.env.INPUT_OWNER = undefined;
process.env.INPUT_REPO = undefined; process.env.INPUT_README = undefined;
process.env.INPUT_ACTION = undefined;" should be changed to actually unset the
env vars (use delete process.env.GITHUB_REPOSITORY; delete
process.env.INPUT_OWNER; delete process.env.INPUT_REPO; delete
process.env.INPUT_README; delete process.env.INPUT_ACTION;) or, better, manage
test envs with Vitest helpers (vi.stubEnv()/vi.unstubAllEnvs()) in your
setup/teardown so the variables are truly removed (apply the same replacement
for the other occurrences of process.env assignments like the ones later for
INPUT_* variables).

Comment on lines 161 to 175
test('loadDefaultConfig from github context GITHUB_REPOSITORY env var', ({ task }) => {
vi.stubEnv('GITHUB_REPOSITORY', 'user2/test2');
delete process.env.INPUT_USER;
delete process.env.INPUT_REPO;
process.env.INPUT_USER = undefined;
process.env.INPUT_REPO = undefined;
const log = new LogTask(task.name);
const config = new Provider();
const result = loadDefaultConfig(log, config);
expect(result.get('owner')).toBe('user2');
expect(result.get('repo')).toBe('test2');
});
test('loadDefaultConfig from provided context payload', ({ task }) => {
delete process.env.INPUT_USER;
delete process.env.INPUT_REPO;
delete process.env.GITHUB_REPOSITORY;
process.env.INPUT_USER = undefined;
process.env.INPUT_REPO = undefined;
process.env.GITHUB_REPOSITORY = undefined;
vi.stubEnv('GITHUB_REPOSITORY', '');
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find the implementation of loadDefaultConfig
rg -t ts -t tsx "function loadDefaultConfig|const loadDefaultConfig" -A 15

Repository: bitflight-devops/github-action-readme-generator

Length of output: 118


🏁 Script executed:

# Also search for INPUT_OWNER and INPUT_USER to understand what's used
rg -t ts -t tsx "INPUT_OWNER|INPUT_USER|INPUT_REPO" -B 2 -A 2

Repository: bitflight-devops/github-action-readme-generator

Length of output: 118


🏁 Script executed:

# Examine the test file to see the broader context
cat -n __tests__/inputs.test.ts | head -200

Repository: bitflight-devops/github-action-readme-generator

Length of output: 9075


🏁 Script executed:

rg -t ts "function loadDefaultConfig|const loadDefaultConfig|export.*loadDefaultConfig" -A 30 src/

Repository: bitflight-devops/github-action-readme-generator

Length of output: 1674


🏁 Script executed:

# Also search for where INPUT_USER and INPUT_OWNER are used in src/
rg -t ts "INPUT_USER|INPUT_OWNER" src/ -B 2 -A 2

Repository: bitflight-devops/github-action-readme-generator

Length of output: 436


🏁 Script executed:

# Let me verify if INPUT_REPO is also used (it appears in the implementation)
rg -t ts "process.env.INPUT_REPO|process.env.INPUT_OWNER" src/ -B 3 -A 1

Repository: bitflight-devops/github-action-readme-generator

Length of output: 553


🏁 Script executed:

# Check Vitest documentation on stubEnv vs direct assignment
# First, let's see how other tests in the file handle env vars
grep -n "process.env\.\|vi.stubEnv" __tests__/inputs.test.ts | head -30

Repository: bitflight-devops/github-action-readme-generator

Length of output: 1627


Clear INPUT_OWNER/INPUT_REPO using vi.stubEnv() for proper test isolation.

loadDefaultConfig reads process.env.INPUT_OWNER and process.env.INPUT_REPO. The current test clears INPUT_USER (which the function doesn't use) via direct assignment, creating env bleed and test fragility. Use vi.stubEnv() to ensure clean isolation:

Suggested fix
-        process.env.INPUT_USER = undefined;
-        process.env.INPUT_REPO = undefined;
+        vi.stubEnv('INPUT_OWNER', '');
+        vi.stubEnv('INPUT_REPO', '');
🤖 Prompt for AI Agents
In `@__tests__/inputs.test.ts` around lines 161 - 175, The test is not properly
isolating environment variables: replace direct assignments to
process.env.INPUT_USER and process.env.INPUT_REPO with vi.stubEnv calls that
explicitly stub/clear INPUT_OWNER and INPUT_REPO (and any other inputs used by
loadDefaultConfig) so the test for loadDefaultConfig (tests named
"loadDefaultConfig from github context GITHUB_REPOSITORY env var" and
"loadDefaultConfig from provided context payload") uses
vi.stubEnv('INPUT_OWNER', '') and vi.stubEnv('INPUT_REPO', '') (and
vi.stubEnv('GITHUB_REPOSITORY', '') where needed) instead of setting unrelated
INPUT_USER or mutating process.env directly to ensure proper test isolation.

Comment on lines +144 to +156
### Optional Fields

| Field | Type | Default | Valid Values | Description |
| ----------------- | ------ | ----------- | ---------------------------------------------------------- | --------------------------------------- |
| `model` | string | `inherit` | `sonnet`, `opus`, `haiku`, `inherit` | Claude model to use |
| `tools` | string | (all tools) | Comma-separated: `Read, Grep, Glob, Bash, Edit, Write` | Tools available to agent |
| `disallowedTools` | string | (none) | Comma-separated tool names | Tools explicitly forbidden |
| `permissionMode` | string | (inherit) | `dontAsk`, `plan`, `acceptEdits`, `acceptAll` | Permission behavior |
| `skills` | string | (none) | Comma-separated skill names | Skills to load |
| `color` | string | (none) | `cyan`, `yellow`, `orange`, `green`, `red` | Visual distinction in UI |
| `hooks` | N/A | N/A | **NOT VALID IN AGENT FRONTMATTER** (use plugin hooks.json) | Hooks are plugin-level, not agent-level |

**CRITICAL**: The `hooks` field is NOT valid in agent frontmatter. Hooks are configured at the plugin or project level in `hooks/hooks.json` or `.claude-plugin/plugin.json`.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "agent-schema.md" -o -name "SKILL.md" -o -name "agent-templates.md" | grep -E "(agent-schema|SKILL|agent-templates)"

Repository: bitflight-devops/github-action-readme-generator

Length of output: 346


🏁 Script executed:

cat -n ./.claude/skills/agent-creator/references/agent-schema.md

Repository: bitflight-devops/github-action-readme-generator

Length of output: 17023


🏁 Script executed:

sed -n '144,156p' ./.claude/skills/agent-creator/references/agent-templates.md

Repository: bitflight-devops/github-action-readme-generator

Length of output: 1618


🏁 Script executed:

cat -n ./.claude/skills/agent-creator/SKILL.md

Repository: bitflight-devops/github-action-readme-generator

Length of output: 37120


Update agent-templates.md to reflect that hooks field is valid in agent frontmatter.

The table at lines 144-156 incorrectly states hooks are "NOT VALID IN AGENT FRONTMATTER." Per agent-schema.md and SKILL.md, hooks is a documented optional field (type: object) that supports lifecycle hook configurations scoped to individual agents. Update the table entry for hooks to show the field as valid with proper description, matching the specification in agent-schema.md (lines 236-277).

🤖 Prompt for AI Agents
In @.claude/skills/agent-creator/references/agent-templates.md around lines 144
- 156, Update the agent-templates.md table row for the `hooks` field to mark it
as a valid agent frontmatter field (type: object, default: (none)) and replace
the "NOT VALID IN AGENT FRONTMATTER" note with a concise description like
"Lifecycle hook configurations scoped to individual agents (see agent-schema.md
for supported hook keys)"; ensure the `hooks` row matches the specification in
agent-schema.md and SKILL.md so the table shows the correct type and description
for `hooks`.

Comment on lines +5 to +8
**Stack**: TypeScript 5.7.3, Node.js 20.x, ESM with dual CJS/ESM output
**Linter**: Biome 2.x (replaces ESLint + Prettier)
**Test Framework**: Vitest
**Build**: esbuild
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for Prettier configuration files
fd -e 'prettierrc' -e 'prettierrc.json' -e 'prettierrc.js' -e 'prettierrc.yaml' -e 'prettierrc.yml'

Repository: bitflight-devops/github-action-readme-generator

Length of output: 73


🏁 Script executed:

# Check package.json for Prettier dependency and scripts
find . -maxdepth 2 -name 'package.json' -type f | head -5 | xargs grep -l 'prettier' 2>/dev/null

Repository: bitflight-devops/github-action-readme-generator

Length of output: 105


🏁 Script executed:

# Check for Biome configuration
fd -e 'biome.json'

Repository: bitflight-devops/github-action-readme-generator

Length of output: 73


🏁 Script executed:

# Look for any prettier references in the project
rg -i 'prettier' --type json --type yaml --type markdown -l | head -20

Repository: bitflight-devops/github-action-readme-generator

Length of output: 182


🏁 Script executed:

# Read the specific file being reviewed to understand context
cat -n '.claude/skills/holistic-linting/PROJECT-CONFIG.md' | head -30

Repository: bitflight-devops/github-action-readme-generator

Length of output: 1092


🏁 Script executed:

cat package.json | jq '.dependencies, .devDependencies' 2>/dev/null || cat package.json

Repository: bitflight-devops/github-action-readme-generator

Length of output: 1268


🏁 Script executed:

# Search for any Prettier usage in configuration or scripts
rg -i 'prettier' -B 2 -A 2

Repository: bitflight-devops/github-action-readme-generator

Length of output: 14625


Clarify Biome's scope in the wording.

Prettier is still actively used as a runtime dependency for markdown and YAML formatting, and for non-JS files via lint-staged. The statement "Biome replaces ESLint + Prettier" overstates Biome's role. Revise to clarify Biome is the primary formatter for TypeScript/JavaScript only.

Suggested wording
-**Linter**: Biome 2.x (replaces ESLint + Prettier)
+**Linter**: Biome 2.x (replaces ESLint; primary formatter for TS/JS)
📝 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
**Stack**: TypeScript 5.7.3, Node.js 20.x, ESM with dual CJS/ESM output
**Linter**: Biome 2.x (replaces ESLint + Prettier)
**Test Framework**: Vitest
**Build**: esbuild
**Stack**: TypeScript 5.7.3, Node.js 20.x, ESM with dual CJS/ESM output
**Linter**: Biome 2.x (replaces ESLint; primary formatter for TS/JS)
**Test Framework**: Vitest
**Build**: esbuild
🤖 Prompt for AI Agents
In @.claude/skills/holistic-linting/PROJECT-CONFIG.md around lines 5 - 8, Update
the "Linter: Biome 2.x (replaces ESLint + Prettier)" line in PROJECT-CONFIG.md
to clarify scope: change it to state that Biome 2.x is the primary
linter/formatter for TypeScript/JavaScript only, and explicitly note that
Prettier remains a runtime dependency used for Markdown/YAML formatting and for
non-JS files via lint-staged; edit the existing "Linter: Biome 2.x (replaces
ESLint + Prettier)" text to this clarified phrasing so readers understand Biome
does not fully replace Prettier.

Comment on lines 46 to 49
- name: Install compatible Nodejs version
id: setup-node
uses: ./.github/actions/setup-node

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find the setup-node action.yml file
fd -t f 'action.yml' .github/actions/setup-node

Repository: bitflight-devops/github-action-readme-generator

Length of output: 128


🏁 Script executed:

# Read the action.yml file to inspect the input metadata
cat -n .github/actions/setup-node/action.yml

Repository: bitflight-devops/github-action-readme-generator

Length of output: 2630


🌐 Web query:

GitHub Actions input schema supported keys documentation

💡 Result:

Workflow inputs (in workflow YAML)

on: workflow_dispatch: inputs:

Supported per-input keys:

  • description
  • required
  • default
  • type (boolean, choice, number, environment, string)
  • options (only relevant when type: choice)
    Docs: Workflow syntax → on.workflow_dispatch.inputs. [1]

on: workflow_call: inputs: (reusable workflows)

Supported per-input keys:

  • description
  • required
  • default
  • type (required; boolean, number, string)
    Docs: Workflow syntax → on.workflow_call.inputs. [1]

Action inputs (in action.yml / action.yaml)

Supported per-input keys:

  • description (required)
  • required
  • default
  • deprecationMessage
    Docs: Metadata syntax → inputs.<input_id>.*. [2]

Sources

  • [1] GitHub Docs — Workflow syntax for GitHub Actions (sections on.workflow_dispatch.inputs and on.workflow_call.inputs). (docs.github.com)
  • [2] GitHub Docs — Metadata syntax reference for GitHub Actions (section inputs). (docs.github.com)

Citations:


Remove unsupported type key from action input metadata.

The type: string key on line 9 of .github/actions/setup-node/action.yml is not a supported input property in GitHub Actions action metadata. The supported properties for action inputs are description, required, default, and deprecationMessage only. Remove the type: string line to resolve actionlint validation errors.

🧰 Tools
🪛 actionlint (1.7.10)

[error] 48-48: could not parse action metadata in "/home/jailuser/git/.github/actions/setup-node": line 5: unexpected key "type" for definition of input "version"

(action)

🤖 Prompt for AI Agents
In @.github/workflows/push_code_linting.yml around lines 46 - 49, Remove the
unsupported "type: string" input property from the action metadata in
.github/actions/setup-node/action.yml (the input defined for the custom action
used by the setup-node step), leaving only supported input keys (description,
required, default, deprecationMessage); locate the input block that contains
"type: string" (used by the setup-node action referenced in the workflow) and
delete that line so actionlint validation passes.

Comment on lines +54 to +62
- name: Setup Biome
uses: biomejs/setup-biome@v2
with:
version: latest

- run: npm install

- name: Biome check
run: biome check ./src/ ./__tests__/
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

biomejs/setup-biome version latest pinning best practices

💡 Result:

Latest biomejs/setup-biome version

The latest release is v2.7.0 (Jan 10, 2026). [1]

Pinning best practices (recommended order)

  1. Most secure (supply-chain hardening): pin the action to a full commit SHA (immutable). GitHub explicitly recommends SHA pinning for third-party actions. [2]
    - uses: biomejs/setup-biome@<full-40-char-sha> # corresponds to the v2.7.0 release commit
  2. Good stability (common compromise): pin to an exact release tag (reproducible, but tags can be moved):
    - uses: biomejs/setup-biome@v2.7.0
  3. Acceptable for auto-updates within a major: pin to the major tag (gets non-breaking updates automatically):
    - uses: biomejs/setup-biome@v2

Pin the Biome CLI version too (for reproducible formatting/lint results)

  • Prefer pinning @biomejs/biome in your project lockfile/dependencies and let the action auto-detect from lockfiles. The action docs recommend this, and warn that semver ranges can float to a higher version if it falls back to package.json. [1]

What to avoid (unless you truly want drift)

  • Avoid with: { version: latest } if you need deterministic CI results (it will intentionally float). [1]

Sources: [1] [2]


🌐 Web query:

Biome latest release version 2025 2026

💡 Result:

As of February 3, 2026, the latest Biome (Biome CLI / @biomejs/biome) release is:

  • v2.3.13, released January 26, 2026. [1]

(For additional confirmation across package/version trackers, third-party indexes also list Biome in the 2.3.x line with frequent releases.) [2]


🌐 Web query:

GitHub biomejs/setup-biome action documentation

💡 Result:

biomejs/setup-biome is a first-party GitHub Action for installing the Biome CLI in GitHub Actions runners. Docs are in the repo README and mirrored on the GitHub Marketplace listing. [1][2]

Official docs

  • Repo README: biomejs/setup-biome [1]
  • GitHub Marketplace page: “Setup Biome” [2]
  • Biome CI recipe (shows a full workflow example): “Continuous Integration → GitHub Actions” [3]

Inputs

  • version (optional): Biome CLI version to install (e.g. 2.3.5 or latest). If omitted, the action tries to auto-detect from lockfiles / package.json, otherwise installs latest. [1][2]
  • token (optional): GitHub token for API requests (defaults to ${{ github.token }}). [1][2]
  • working-dir (optional): directory to search for lockfiles when auto-detecting. [1][2]

Minimal workflow example

- uses: actions/checkout@v4
- uses: biomejs/setup-biome@v2
- run: biome ci .

[1][3]


Remove version: latest from Biome setup to avoid CI drift.

Using version: latest breaks reproducibility—Biome may update to a new version mid-development cycle and alter linting/formatting results. Official biomejs/setup-biome docs recommend either pinning an explicit version or removing the parameter entirely to let the action auto-detect from your package-lock.json or similar lockfile. If no lockfile is found, it falls back to the latest release, but that's rare. The suggested fix below removes the version parameter and relies on auto-detection—keep your @biomejs/biome dependency pinned in your lockfile for full determinism.

Suggested change
      - name: Setup Biome
        uses: biomejs/setup-biome@v2
-       with:
-         version: latest
🤖 Prompt for AI Agents
In @.github/workflows/test.yml around lines 54 - 62, Remove the hard-coded
"version: latest" parameter from the Biome setup step that uses
biomejs/setup-biome@v2 in the GitHub Actions workflow; edit the "Setup Biome"
step to drop the "version: latest" line so the action auto-detects the version
from your lockfile (ensure `@biomejs/biome` is pinned in
package-lock.json/yarn.lock for deterministic runs).

Comment on lines +61 to 73
"format": "biome format --write ./src ./__tests__",
"format:check": "biome format ./src ./__tests__",
"format:prettier": "prettier --write . --config .prettierrc.cjs --ignore-unknown",
"generate-docs": "echo 'Generating docs';node dist/bin/index.js && git add README.md ./.github/ghadocs .ghadocs.json || true",
"postinstall": "echo '✨ Successfully Installed'",
"prelint": "npm run format && tsc --project tsconfig.json --noemit",
"lint": "npm run lint:eslint && npm run lint:markdown",
"lint:fix": "npm run lint:eslint:fix && npm run lint:markdown:fix",
"lint:eslint": "eslint --color ./src/ ./__tests__/",
"lint:eslint:fix": "eslint --color --fix ./src/ ./__tests__/",
"lint": "npm run lint:biome && npm run lint:markdown",
"lint:fix": "npm run lint:biome:fix && npm run lint:markdown:fix",
"lint:biome": "biome lint ./src/ ./__tests__/",
"lint:biome:fix": "biome lint --write ./src/ ./__tests__/",
"check": "biome check ./src/ ./__tests__/",
"check:fix": "biome check --write ./src/ ./__tests__/",
"markdownlint": "markdownlint",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, get the line count of package.json to understand its size
wc -l package.json

Repository: bitflight-devops/github-action-readme-generator

Length of output: 107


🏁 Script executed:

# Examine package.json around the disputed lines and Node engine requirements
sed -n '55,115p' package.json
sed -n '180,200p' package.json

Repository: bitflight-devops/github-action-readme-generator

Length of output: 2994


🏁 Script executed:

# Check for presence of ESLint and Prettier config files
fd -e 'eslintrc.*' -e 'prettierrc.*' --type f

Repository: bitflight-devops/github-action-readme-generator

Length of output: 73


🏁 Script executed:

# Check the copilot-instructions.md to verify current guidelines
cat -n .github/copilot-instructions.md | head -100

Repository: bitflight-devops/github-action-readme-generator

Length of output: 4233


🏁 Script executed:

# Also check if there's a .node-version file or volta config
cat .node-version 2>/dev/null || echo "No .node-version file"

Repository: bitflight-devops/github-action-readme-generator

Length of output: 95


🏁 Script executed:

# Check for ESLint and Prettier config files
ls -la .eslintrc.* .prettierrc.* 2>&1 | head -20

Repository: bitflight-devops/github-action-readme-generator

Length of output: 214


🏁 Script executed:

# Check full engines section in package.json to get exact line numbers
sed -n '186,195p' package.json

Repository: bitflight-devops/github-action-readme-generator

Length of output: 281


Update coding guidelines or restore ESLint + tighten Node engine requirement.

The project has two undocumented policy violations:

  1. Tooling mismatch (lines 61–73, 107–109): Package.json and lint-staged route TypeScript/JSON formatting and linting through Biome, but .github/copilot-instructions.md (line 12) documents the standard as ESLint + Prettier. ESLint config (.eslintrc.cjs) is completely missing; Prettier config exists but is unused in the active workflow.

  2. Node engine drift (line 187–190): Documented guideline enforces strict Node 20.x (>=20.0.0 <21.0.0), but engines.node is set to >=20.0.0 <26.0.0, permitting Node 21–25.

Either update .github/copilot-instructions.md to codify Biome + the broader Node range, or restore the ESLint/Prettier tooling and revert engines to <21.0.0.

🤖 Prompt for AI Agents
In `@package.json` around lines 61 - 73, The package.json scripts declare
Biome-based formatting/linting (scripts like "format", "format:check",
"lint:biome", "lint:biome:fix") and the engines.node range allows >=20.0.0
<26.0.0, which conflicts with project docs that expect ESLint+Prettier and Node
20.x; either (A) update docs to reflect Biome and the relaxed engines.node range
OR (B) restore ESLint/Prettier tooling and tighten engines.node to <21.0.0: if
choosing B, add back an ESLint config (.eslintrc.cjs), switch package.json
scripts to use eslint and prettier (replace "lint:biome"/"format" with
"lint"/"format" commands that invoke eslint and prettier), update lint-staged if
present to run eslint --fix/prettier --write for TS/JSON, and change the
engines.node entry to ">=20.0.0 <21.0.0"; if choosing A, update
.github/copilot-instructions.md to document Biome as the standard and optionally
keep engines.node as-is.

Comment on lines 76 to 84
type Steps = {
'shell'?: string;
'if'?: string;
'run'?: string;
'name'?: string;
'id'?: string;
shell?: string;
if?: string;
run?: string;
name?: string;
id?: string;
'working-directory'?: string;
'env': { [key: string]: string };
env: { [key: string]: string };
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the current state of src/Action.ts around lines 76-84
head -n 90 src/Action.ts | tail -n +70

Repository: bitflight-devops/github-action-readme-generator

Length of output: 468


🏁 Script executed:

# Let's also check if there's an action.yml file to understand the schema
find . -name "action.yml" -o -name "action.yaml" | head -20

Repository: bitflight-devops/github-action-readme-generator

Length of output: 143


🏁 Script executed:

# Search for references to the Steps type or env field definitions
rg -n "type Steps" -A 10 src/

Repository: bitflight-devops/github-action-readme-generator

Length of output: 447


🏁 Script executed:

# Let's check the action.yml to see how it defines steps
cat action.yml

Repository: bitflight-devops/github-action-readme-generator

Length of output: 4045


🏁 Script executed:

# Let's also search for any tests or examples that show how Steps is used
rg -n "env:" src/ -B 2 -A 2 --type ts | head -50

Repository: bitflight-devops/github-action-readme-generator

Length of output: 789


🌐 Web query:

GitHub Actions composite steps env field optional required

💡 Result:

In a composite action (runs: using: composite), the env: field on a step (runs.steps[*].env) is optional, not required—it’s only used when you want to define environment variables scoped to that specific step. [1]

If you need to persist or modify environment variables beyond a single step (i.e., for later steps), GitHub recommends writing to $GITHUB_ENV from a run: step, rather than relying on env:. [1]

Example of optional per-step env: usage in a composite action: [2]


Make env optional in composite steps.

The env field is optional in GitHub Actions composite step definitions; requiring it will incorrectly reject valid step configurations that don't include environment variables.

Suggested fix
-  env: { [key: string]: string };
+  env?: { [key: string]: string };
📝 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
type Steps = {
'shell'?: string;
'if'?: string;
'run'?: string;
'name'?: string;
'id'?: string;
shell?: string;
if?: string;
run?: string;
name?: string;
id?: string;
'working-directory'?: string;
'env': { [key: string]: string };
env: { [key: string]: string };
};
type Steps = {
shell?: string;
if?: string;
run?: string;
name?: string;
id?: string;
'working-directory'?: string;
env?: { [key: string]: string };
};
🤖 Prompt for AI Agents
In `@src/Action.ts` around lines 76 - 84, The Steps type currently requires an env
property which is optional in GitHub Actions composite steps; update the Steps
type definition by making env optional (change env: { [key: string]: string } to
env?: { [key: string]: string }) and adjust any code that assumes env is always
present to handle undefined (e.g., checks in functions that read Steps.env).
This touches the Steps type declaration in Action.ts and any consumers that
iterate or spread step.env should guard for undefined.

Comment on lines +70 to +74
generateSvgImage(
svgPath: string | undefined,
icon: Partial<FeatherIconNames> = DEFAULT_BRAND_ICON,
bgcolor: Partial<BrandColors> = DEFAULT_BRAND_COLOR
): Promise<void> {
): void {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find generateSvgImage call sites and any promise-style usage.
echo "=== All generateSvgImage call sites ==="
rg -n -C2 '\bgenerateSvgImage\s*\('

echo ""
echo "=== Await usage with generateSvgImage ==="
rg -nP -C2 '\bawait\s+[^;]*\bgenerateSvgImage\s*\('

echo ""
echo "=== .then() chaining with generateSvgImage ==="
rg -nP -C2 '\bgenerateSvgImage\s*\([^)]*\)\.then\b'

echo ""
echo "=== Method implementation context (lines 60-100 of svg-editor.mts) ==="
sed -n '60,100p' src/svg-editor.mts

Repository: bitflight-devops/github-action-readme-generator

Length of output: 3247


Update JSDoc return type to match actual implementation.

The method correctly returns void and no callers rely on Promise behavior. However, the JSDoc comment at line 68 incorrectly documents @returns {Promise<void>} and should be updated to @returns {void}.

🤖 Prompt for AI Agents
In `@src/svg-editor.mts` around lines 70 - 74, Update the JSDoc for
generateSvgImage so the `@returns` tag matches the implementation: change the
documented return type from Promise<void> to void in the JSDoc above the
generateSvgImage method; ensure the JSDoc now reads `@returns` {void} and remove
any mention of async/Promise semantics to avoid confusion for callers and
maintainers.

- Bump minimum Node version to 20.11.0 for native ESM dirname/filename
- Replace fileURLToPath polyfills with import.meta.dirname/filename
- Remove dead __filename/__dirname exports from helpers.ts
- Update test files to use native import.meta.dirname

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
package.json (1)

201-203: ⚠️ Potential issue | 🟠 Major

Volta node version (20.9.0) is below the engines minimum (20.11.0).

The volta.node version 20.9.0 is less than the engines.node minimum of 20.11.0. Developers using Volta will get Node 20.9.0, which doesn't support import.meta.dirname natively, causing runtime failures.

🔧 Suggested fix
   "volta": {
-    "node": "20.9.0"
+    "node": "20.11.0"
   }

- Modify linting-root-cause-resolver agent for TypeScript/Biome workflows
- Modify post-linting-architecture-reviewer for TypeScript patterns
- Rewrite holistic-linting skill for Biome instead of ruff/mypy/pyright
- Fix CI biomejs/setup-biome token conflict (remove duplicate GITHUB_TOKEN env)

The linting infrastructure now focuses on:
- Biome rules and resolution workflows
- TypeScript compiler error resolution
- Project-specific patterns (node: prefix, .js extensions, type guards)

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
- Preserve equivalent detail from Python workflows for TypeScript/Biome
- Biome Resolution Workflow with 6 detailed steps and fix examples
- TypeScript Compiler Resolution Workflow with 6 detailed steps
- Common fix patterns for all major Biome rules (noExplicitAny, useAwait, etc.)
- TypeScript fix strategies (type narrowing, type predicates, etc.)
- Rules Knowledge Base section with Biome and TypeScript references
- Integration with Git Hooks section
- Example 3 showing multi-violation resolution
- Add delegate skill for sub-agent prompt construction

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/push_code_linting.yml:
- Around line 56-61: The reviewdog step ("Biome reviewdog" using
mongolyy/reviewdog-action-biome@v1 with inputs reporter, github_token and
fail_on_error) must be skipped for fork PRs because GITHUB_TOKEN is read-only;
add a conditional to the step (an if: expression) so it only runs when the PR
comes from the same repository (e.g., check github.event_name != 'pull_request'
OR github.event.pull_request.head.repo.full_name == github.repository, or use
github.event.pull_request.head.repo.owner == github.repository_owner) to avoid
executing the action on forked PRs and prevent permission errors from the
github_pr_review reporter failing with fail_on_error: true.
🧹 Nitpick comments (1)
.github/workflows/push_code_linting.yml (1)

37-51: Consider pinning Biome version for reproducible linting results.

Using version: latest will re-evaluate on every workflow run. Two better approaches:

  1. Recommended: Pin @biomejs/biome to an exact version in package.json/lockfile (e.g., npm install -D -E @biomejs/biome@2.3.13), then omit the version input to let the action auto-detect.
  2. Alternative: Explicitly set version: 2.3.13 in the action input.

The repo variable approach is also valid, but pinning in project dependencies ensures consistency across all tooling that uses Biome.

Comment on lines +56 to +61
- name: Biome reviewdog
uses: mongolyy/reviewdog-action-biome@v1
with:
reporter: github-pr-review # Change reporter.
eslint_flags: src/
reporter: github-pr-review
github_token: ${{ secrets.GITHUB_TOKEN }}
fail_on_error: true
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

GitHub Actions GITHUB_TOKEN permissions pull_request fork read-only

💡 Result:

  • pull_request workflows from a fork (public repos): GitHub runs these with no repository secrets (except GITHUB_TOKEN) and the GITHUB_TOKEN is read-only, so steps that try to write (comment/label/push, create releases, etc.) will fail. You generally cannot “upgrade” it to write via permissions: for fork PR runs. [1], [2]
  • Dependabot PRs: Treated like fork PRs, so they also get a read-only GITHUB_TOKEN and no secrets. [1], [3]
  • pull_request_target: Runs in the base repo’s default-branch context (trusted workflow), and is intended for things like labeling/commenting on fork PRs; however, it has important security implications if you check out/run PR code. GitHub warns that running untrusted PR code under pull_request_target can lead to vulnerabilities (including unintended access to secrets/write privileges). [1]
  • Private/internal repos (fork PRs): Org/enterprise settings can allow more, including sending a write token and/or secrets to fork PR workflows; by default it’s read-only GITHUB_TOKEN and no secrets. [4]
  • Repo/workflow-level permissions controls: You can restrict/expand GITHUB_TOKEN scopes with permissions: (missing scopes become none), but public-fork PRs remain a special case that still receive a read token. [2], [5]

Sources
[1] GitHub Docs – “Events that trigger workflows” (fork PR restrictions; pull_request_target behavior/warnings) (docs.github.com)
[2] GitHub Changelog – “Control permissions for GITHUB_TOKEN” (permissions key; fork PRs special case read token) (github.blog)
[3] GitHub Changelog – Dependabot PRs treated as forks (read-only token, no secrets) (github.blog)
[4] GitHub Docs – Org Actions settings (private forks: read-only default; can allow write tokens/secrets) (docs.github.com)
[5] GitHub Docs – “Use GITHUB_TOKEN for authentication in workflows” (using permissions: to scope token) (docs.github.com)

Citations:


🌐 Web query:

reviewdog github-pr-review permission denied fork pull request

💡 Result:

This happens because PRs from forks (and Dependabot PRs) run with a read-only GITHUB_TOKEN and no repository secrets, so reviewdog can’t call the PR Review API to create review comments—resulting in “permission denied” / “Resource not accessible by integration”. GitHub explicitly documents that forked-PR runs get a read-only GITHUB_TOKEN and no secrets. [2] Dependabot PRs are treated the same way. [3]

Fix options

  1. Use a reporter that works on fork PRs (recommended for public OSS)

    • Configure reviewdog to use Checks/annotations instead of PR review comments, e.g. -reporter=github-pr-check or -reporter=github-pr-annotations.
    • reviewdog itself notes it will gracefully degrade on fork PRs by posting GitHub Actions annotations when it can’t write Checks/Reviews with GITHUB_TOKEN. [1]
  2. If you must post PR review comments on fork PRs

    • Run the workflow on pull_request_target so it executes in the base repo context (so it can have write permissions and access to secrets). GitHub warns this is privileged and must be handled carefully (don’t check out / run untrusted fork code). [2]
    • Then provide a real write-capable credential (PAT/GitHub App token) to reviewdog’s github-pr-review reporter, which requires a GitHub API token. [1]
  3. If the PR is not from a fork but still fails

    • Ensure your workflow sets appropriate permissions (e.g. permissions: pull-requests: write) and that org/repo “Workflow permissions” settings aren’t restricting the token by default. [4]

Sources: reviewdog README (reporters + fork graceful degradation) [1]; GitHub Docs (forked PR token/secrets + pull_request_target security warning) [2]; GitHub changelog (Dependabot read-only token) [3]; GitHub Docs (workflow token default permissions settings) [4].


🌐 Web query:

GitHub Actions fork PR GITHUB_TOKEN limited permissions write restrictions

💡 Result:

For workflows triggered by pull_request from a fork (including Dependabot PRs), GitHub intentionally restricts what the workflow can do:

  • GITHUB_TOKEN is read-only for PRs from forked repositories, and repo secrets are not passed (secrets evaluate to empty). This is a security boundary to prevent untrusted fork code from writing to your repo or exfiltrating secrets. [1][2][3]
  • Because of that boundary, you typically cannot “fix it” by adding permissions: …: write in the workflow for fork PR runs—the token remains effectively non-write for the base repo in this scenario. [1][2]

What you can do instead (depending on your repo type and goal):

  1. Public repo: keep CI on pull_request (safe), but do privileged actions in a separate trusted workflow

    • Use pull_request_target only for actions like labeling/commenting, because it runs in the base repo context and can have write + secrets. Do not check out / build / run PR code under pull_request_target (this is the classic “pwn request” risk). [1][2]
    • Or use a two-step design: run untrusted tests on pull_request, then a privileged workflow on workflow_run after it completes (and optionally after approval), since workflow_run can access secrets/write tokens even if the prior run couldn’t. [1]
  2. Require maintainer approval before running fork PR workflows (public repos)

    • GitHub can require manual approval for first-time/external contributors’ fork PR workflow runs. [4][5]
  3. Private/internal repos: optionally allow write tokens/secrets for fork PRs via repo/org/enterprise settings

    • In Actions settings, you can explicitly enable policies like “Send write tokens to workflows from pull requests” and/or “Send secrets…” for fork PRs (private/internal only). [5][6]
  4. If you truly need write access during PR checks

    • Use a GitHub App installation token or a PAT stored as a secret (but note: secrets are still not available to fork-PR pull_request runs; you’d need a trusted trigger/approval pattern such as pull_request_target/workflow_run to use them safely). [3][1]

Sources:
[1] GitHub Docs – events / fork PR restrictions / pull_request_target + workflow_run notes: https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows
[2] GitHub Blog – fork PRs run with read-only token + no secrets; pull_request_target rationale: https://github.blog/news-insights/product-news/github-actions-improvements-for-fork-and-pull-request-workflows/
[3] GitHub Docs – controlling GITHUB_TOKEN permissions, and using App/PAT if needed: https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token
[4] GitHub Docs – approving workflow runs from forks: https://docs.github.com/en/actions/how-tos/manage-workflow-runs/approve-runs-from-forks
[5] GitHub Docs – repo settings for fork PR workflows / approvals: https://docs.github.com/en/enterprise-cloud@latest/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository
[6] GitHub Docs (GHES policy example) – fork PR workflow policies including sending write tokens/secrets: https://docs.github.com/en/enterprise-server%403.18/admin/enforcing-policies/enforcing-policies-for-your-enterprise/enforcing-policies-for-github-actions-in-your-enterprise


Guard reviewdog on fork PRs to avoid permission failures.

On pull_request from forks, GITHUB_TOKEN is read-only, causing github-pr-review to fail with permission denied. With fail_on_error: true, the job stops. Skip this step for fork PRs:

🛡️ Suggested guard
       - name: Biome reviewdog
+        if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false }}
         uses: mongolyy/reviewdog-action-biome@v1
         with:
           reporter: github-pr-review
           github_token: ${{ secrets.GITHUB_TOKEN }}
           fail_on_error: true
🤖 Prompt for AI Agents
In @.github/workflows/push_code_linting.yml around lines 56 - 61, The reviewdog
step ("Biome reviewdog" using mongolyy/reviewdog-action-biome@v1 with inputs
reporter, github_token and fail_on_error) must be skipped for fork PRs because
GITHUB_TOKEN is read-only; add a conditional to the step (an if: expression) so
it only runs when the PR comes from the same repository (e.g., check
github.event_name != 'pull_request' OR
github.event.pull_request.head.repo.full_name == github.repository, or use
github.event.pull_request.head.repo.owner == github.repository_owner) to avoid
executing the action on forked PRs and prevent permission errors from the
github_pr_review reporter failing with fail_on_error: true.

claude added 10 commits February 3, 2026 10:54
- noForEach: Add exception when index is explicitly used in callback
- useAwait: Note NOT recommended by default, must be enabled
- noEvolvingTypes: Note NOT recommended by default (since v1.6.3)
- useExplicitType: Note nursery category (since v1.9.3)
- noParameterAssign: Document propertyAssignment option

All notes verified against official Biome documentation at biomejs.dev

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Don't document Biome's escape hatches - document the correct TypeScript
idiom. Use for...of with .entries() when index access is needed instead
of relying on forEach exception.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
This project enforces:
- useAwait: error
- noEvolvingTypes: error
- useExplicitType: error
- noParameterAssign: warn

Removed misleading "NOT recommended by default" notes that suggested
these rules might not apply. Agents need to know these are enforced.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Observed technical debt from codebase audit:
- Legacy Node.js patterns
- TypeScript modernization opportunities
- Error handling gaps
- Complexity issues

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
The "Verify README contains expected sections" step was incrementing
CHECKS_FAILED but never exiting with error code. Tests passed even
when validation failed.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
The action was inferring owner/repo from GitHub context which points
to the workflow repo (bitflight-devops/github-action-readme-generator),
not the target test repo. This caused usage examples to generate as
`/@v0.0.0` instead of `owner/repo@version`.

Extract owner and repo from matrix.repo and pass explicitly.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
getCurrentVersionString() reads package.json from CWD which doesn't
work for external repos. Use GitHub API to get latest release tag
from the target repo and pass as version_override.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Tests replicate the conditions where:
- owner/repo detection fails (generates "/@" instead of "owner/repo@")
- version detection fails (generates "undefined" instead of actual version)

6 tests fail with current code, proving bugs exist.
Tests will pass once source fixes are applied.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
- Remove steps that manually passed owner/repo/version_override
- Add validation that checks generated content matches expected owner/repo
- Add validation that version is not invalid (v0.0.0, undefined, etc.)
- Tests will FAIL until source code auto-detection is fixed

The action should auto-detect from target repo's .git/config and package.json,
not require explicit inputs as workarounds.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@__tests__/integration-external-repo.test.ts`:
- Around line 134-539: The failing "BUG REPLICATION" tests either need to be
marked as expected failures or the underlying detection bugs fixed: change the
test declarations for the documented failing cases to use it.fails(...) (instead
of it(...)) to make CI expect failures; OR fix the code paths referenced in the
tests—update getCurrentVersionString to read package.json from the target action
directory (not process.cwd()), ensure repositoryFinder reads .git/config from
the provided target dir and that Inputs honors INPUT_OWNER/INPUT_REPO >
GITHUB_REPOSITORY and falls back to .git/config, and verify ReadmeGenerator uses
the resolved owner/repo/version values—apply whichever approach consistently for
the tests invoking Inputs, getCurrentVersionString, repositoryFinder, and
ReadmeGenerator.

- repositoryFinder() now accepts baseDir param to read .git/config
  from target repo instead of CWD
- getCurrentVersionString() reads package.json from action directory
- loadDefaultConfig() extracts action directory and passes to helpers
- transformGitHubInputsToArgv() skips empty owner/repo values to allow
  auto-detection fallback

Fixes the bug where external repos generated "/@v0.0.0" instead of
correct "owner/repo@version" in usage examples.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
When baseDir is provided (external repo scenario), check .git/config
from that directory BEFORE falling back to GITHUB_REPOSITORY. This is
critical because in CI, GITHUB_REPOSITORY points to the workflow repo,
not the target repo being documented.

Priority order now:
1. Explicit input repo string
2. .git/config from baseDir (when provided)
3. GitHub context / GITHUB_REPOSITORY
4. .git/config from CWD

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Add tests that replicate exact CI conditions:
- GITHUB_REPOSITORY set to workflow repo (not target)
- Target repo in subdirectory with own .git/config
- Validates .git/config from target dir takes priority

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.github/workflows/integration-test.yml:
- Around line 160-176: The workflow currently searches the whole README
(README_CONTENT) for "uses:" and picks the first match (USAGE_LINE), which can
hit non-example occurrences; change the logic to first extract the documented
usage section delimited by HTML comments (e.g., <!-- usage-start --> ... <!--
usage-end -->) into a new variable (e.g., USAGE_SECTION) and then run the
existing grep -E and subsequent extraction (to set USAGE_LINE and USES_VALUE)
against USAGE_SECTION instead of README_CONTENT; if the markers are not present,
fall back to searching README_CONTENT to preserve existing behavior.

In `@src/helpers.ts`:
- Around line 375-387: Remove the redundant accessSync usage and switch to the
existing readFile helper: replace the try block that calls accessSync and
readFileSync(packageJsonPath) with a try that calls readFile(packageJsonPath)
and JSON.parse its result to set packageVersion (preserving the same log.debug
messages and the catch fallback to process.env.npm_package_version), and then
remove the unused accessSync import; update references to packageJsonPath,
packageVersion, readFile, log.debug, and process.env.npm_package_version
accordingly.
🧹 Nitpick comments (1)
__tests__/integration-external-repo.test.ts (1)

58-64: Avoid reassigning process.env; restore in-place instead.

Reassigning process.env replaces Node’s special env proxy and can confuse code that retains references. Prefer restoring keys in-place (or rely solely on vi.unstubAllEnvs() if only using stubEnv).

♻️ Suggested refactor
-    // Restore environment variables
-    process.env = originalEnv;
-    vi.unstubAllEnvs();
+    // Restore environment variables
+    vi.unstubAllEnvs();
+    for (const key of Object.keys(process.env)) {
+      if (!(key in originalEnv)) {
+        delete process.env[key];
+      }
+    }
+    Object.assign(process.env, originalEnv);

Comment on lines +160 to +176
README_CONTENT=$(cat "${{ matrix.readme_path }}")

# Extract the usage line (e.g., "uses: owner/repo@version")
USAGE_LINE=$(echo "$README_CONTENT" | grep -E "uses:\s+\S+/\S+@" | head -1 || echo "")

if [ -z "$USAGE_LINE" ]; then
echo "::error::No 'uses: owner/repo@version' pattern found in README"
echo "README content around usage section:"
echo "$README_CONTENT" | grep -A5 -B5 "uses:" | head -20 || echo "(no uses: found)"
exit 1
fi

echo "Found usage line: $USAGE_LINE"

# Extract the owner/repo@version part
USES_VALUE=$(echo "$USAGE_LINE" | grep -oE "[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+" | head -1 || echo "")

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Test 1: Check grep -E behavior with \s and \S (extended regex)
echo "=== Test 1: grep -E with \s and \S ==="
echo 'uses: owner/repo@v1' | grep -E "uses:\s+\S+/\S+@" && echo "matched with \s and \S" || echo "NO match with \s and \S"

# Test 2: Check with POSIX character classes
echo ""
echo "=== Test 2: grep -E with POSIX character classes ==="
echo 'uses: owner/repo@v1' | grep -E "uses:[[:space:]]+[^[:space:]]+/[^[:space:]]+@" && echo "matched with POSIX" || echo "NO match with POSIX"

# Test 3: Check if different spacing works
echo ""
echo "=== Test 3: Multiple spaces ==="
echo 'uses:    owner/repo@v1' | grep -E "uses:\s+\S+/\S+@" && echo "matched (\\s)" || echo "NO match (\\s)"
echo 'uses:    owner/repo@v1' | grep -E "uses:[[:space:]]+[^[:space:]]+/[^[:space:]]+@" && echo "matched (POSIX)" || echo "NO match (POSIX)"

# Test 4: Check ubuntu-latest info
echo ""
echo "=== Test 4: grep and shell info ==="
grep --version | head -1
bash --version | head -1

# Test 5: Test with the actual pattern from the code
echo ""
echo "=== Test 5: Current code pattern ==="
README_CONTENT=$(cat <<'EOF'
# My Action
Some intro text
## Usage
uses: owner/repo@v1
More instructions
actions/checkout@v2
EOF
)
echo "$README_CONTENT"
echo ""
echo "Grepping for pattern with \\s and \\S:"
echo "$README_CONTENT" | grep -E "uses:\s+\S+/\S+@" | head -1
echo ""
echo "Grepping for pattern with POSIX:"
echo "$README_CONTENT" | grep -E "uses:[[:space:]]+[^[:space:]]+/[^[:space:]]+@" | head -1

Repository: bitflight-devops/github-action-readme-generator

Length of output: 733


🏁 Script executed:

#!/bin/bash

# Check the workflow file to see what README files are being tested
echo "=== Examining integration-test.yml context ==="
cat -n .github/workflows/integration-test.yml | sed -n '150,180p'

# Look for test fixtures to understand what README content is being validated
echo ""
echo "=== Looking for test README files ==="
find . -name "README*" -type f | head -20

# Check if there are examples with unrelated uses: entries
echo ""
echo "=== Checking README files for 'uses:' patterns ==="
find . -name "README*" -type f -exec grep -l "uses:" {} \; 2>/dev/null

# Examine the matrix.readme_path to understand what's being tested
echo ""
echo "=== Looking for matrix configuration ==="
cat -n .github/workflows/integration-test.yml | grep -A10 -B10 "matrix:"

Repository: bitflight-devops/github-action-readme-generator

Length of output: 2543


🏁 Script executed:

#!/bin/bash

# Check the actual README.md to see if there are multiple 'uses:' entries
echo "=== README.md content ==="
cat ./README.md

# Check if there are any 'uses:' entries that are NOT action references
echo ""
echo "=== Checking for 'uses:' in README ==="
grep -n "uses:" ./README.md | head -20

# Test with real README content
echo ""
echo "=== Testing grep patterns with real README ==="
README_CONTENT=$(cat ./README.md)

echo "Testing current pattern (\\s and \\S):"
echo "$README_CONTENT" | grep -E "uses:\s+\S+/\S+@" | head -3

echo ""
echo "Testing POSIX pattern:"
echo "$README_CONTENT" | grep -E "uses:[[:space:]]+[^[:space:]]+/[^[:space:]]+@" | head -3

# Check if there are unrelated 'uses:' entries that would match incorrectly
echo ""
echo "=== All 'uses:' lines in README ==="
echo "$README_CONTENT" | grep "uses:" | head -20

Repository: bitflight-devops/github-action-readme-generator

Length of output: 26148


🏁 Script executed:

#!/bin/bash

# Test the actual behavior with the real README content
echo "=== Testing with actual README content ==="
README_CONTENT=$(cat ./README.md)

echo "Pattern with \\s and \\S (first match only):"
USAGE_LINE=$(echo "$README_CONTENT" | grep -E "uses:\s+\S+/\S+@" | head -1)
echo "First match: $USAGE_LINE"

echo ""
echo "Pattern with POSIX (first match only):"
USAGE_LINE=$(echo "$README_CONTENT" | grep -E "uses:[[:space:]]+[^[:space:]]+/[^[:space:]]+@" | head -1)
echo "First match: $USAGE_LINE"

# Now test the proposed awk extraction
echo ""
echo "=== Testing with awk extraction (proposed fix) ==="
USAGE_SECTION=$(echo "$README_CONTENT" | awk '
  /<!-- start usage -->/ {flag=1; next}
  /<!-- end usage -->/ {flag=0}
  flag
')

echo "Usage section extracted:"
echo "$USAGE_SECTION"
echo ""

echo "Grep on extracted section:"
USAGE_LINE=$(echo "$USAGE_SECTION" | grep -E "uses:[[:space:]]+[^[:space:]]+/[^[:space:]]+@" | head -1)
echo "Match: $USAGE_LINE"

# Extract the uses value from the correct line
echo ""
echo "=== Extracting USES_VALUE from matched line ==="
USES_VALUE=$(echo "$USAGE_LINE" | grep -oE "[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+" | head -1)
echo "USES_VALUE: $USES_VALUE"

Repository: bitflight-devops/github-action-readme-generator

Length of output: 3802


Scope grep pattern to usage section to avoid false matches in README.

The current code scans the entire README and matches the first uses: pattern found. In this README, that's a table row describing the versioning feature (| :white_check_mark: | **Auto-Versioning** | Updates uses: owner/repo@v1.2.3...), not the actual usage example. This causes the workflow to fail when parsing. Extract the usage section first using HTML comments, then apply the pattern.

Suggested fix
          README_CONTENT=$(cat "${{ matrix.readme_path }}")
 
+         # Extract only the usage section to avoid matching unrelated uses: entries
+         USAGE_SECTION=$(echo "$README_CONTENT" | awk '
+           /<!-- start usage -->/ {flag=1; next}
+           /<!-- end usage -->/ {flag=0}
+           flag
+         ')
+
          # Extract the usage line (e.g., "uses: owner/repo@version")
-         USAGE_LINE=$(echo "$README_CONTENT" | grep -E "uses:\s+\S+/\S+@" | head -1 || echo "")
+         USAGE_LINE=$(echo "$USAGE_SECTION" | grep -E "uses:[[:space:]]+[^[:space:]]+/[^[:space:]]+@" | head -1 || true)
📝 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
README_CONTENT=$(cat "${{ matrix.readme_path }}")
# Extract the usage line (e.g., "uses: owner/repo@version")
USAGE_LINE=$(echo "$README_CONTENT" | grep -E "uses:\s+\S+/\S+@" | head -1 || echo "")
if [ -z "$USAGE_LINE" ]; then
echo "::error::No 'uses: owner/repo@version' pattern found in README"
echo "README content around usage section:"
echo "$README_CONTENT" | grep -A5 -B5 "uses:" | head -20 || echo "(no uses: found)"
exit 1
fi
echo "Found usage line: $USAGE_LINE"
# Extract the owner/repo@version part
USES_VALUE=$(echo "$USAGE_LINE" | grep -oE "[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+" | head -1 || echo "")
README_CONTENT=$(cat "${{ matrix.readme_path }}")
# Extract only the usage section to avoid matching unrelated uses: entries
USAGE_SECTION=$(echo "$README_CONTENT" | awk '
/<!-- start usage -->/ {flag=1; next}
/<!-- end usage -->/ {flag=0}
flag
')
# Extract the usage line (e.g., "uses: owner/repo@version")
USAGE_LINE=$(echo "$USAGE_SECTION" | grep -E "uses:[[:space:]]+[^[:space:]]+/[^[:space:]]+@" | head -1 || true)
if [ -z "$USAGE_LINE" ]; then
echo "::error::No 'uses: owner/repo@version' pattern found in README"
echo "README content around usage section:"
echo "$README_CONTENT" | grep -A5 -B5 "uses:" | head -20 || echo "(no uses: found)"
exit 1
fi
echo "Found usage line: $USAGE_LINE"
# Extract the owner/repo@version part
USES_VALUE=$(echo "$USAGE_LINE" | grep -oE "[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+@[A-Za-z0-9_.-]+" | head -1 || echo "")
🤖 Prompt for AI Agents
In @.github/workflows/integration-test.yml around lines 160 - 176, The workflow
currently searches the whole README (README_CONTENT) for "uses:" and picks the
first match (USAGE_LINE), which can hit non-example occurrences; change the
logic to first extract the documented usage section delimited by HTML comments
(e.g., <!-- usage-start --> ... <!-- usage-end -->) into a new variable (e.g.,
USAGE_SECTION) and then run the existing grep -E and subsequent extraction (to
set USAGE_LINE and USES_VALUE) against USAGE_SECTION instead of README_CONTENT;
if the markers are not present, fall back to searching README_CONTENT to
preserve existing behavior.

Comment on lines +375 to 387
try {
accessSync(packageJsonPath);
const packageData: Partial<PackageJson> = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
packageVersion = packageData.version;
log.debug(`version string from target repo package.json: ${packageVersion ?? 'not found'}`);
} catch (error) {
log.debug(`package.json not found at ${packageJsonPath}. ${error}`);
// Fall back to npm_package_version for backward compatibility when running from same directory
packageVersion = process.env.npm_package_version;
log.debug(
`Falling back to env:npm_package_version: ${packageVersion ?? 'not found'}`,
);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove redundant accessSync and use the readFile helper for consistency.

The accessSync check on line 376 is redundant since readFileSync will throw if the file doesn't exist, and the try/catch already handles this. This pattern also introduces a minor TOCTOU (time-of-check-time-of-use) race condition. Additionally, this code uses readFileSync directly instead of the readFile helper defined at line 148.

This is likely the source of the pipeline failure (Biome lint warning).

🔧 Proposed fix
     const actionDir = path.dirname(inputs.action.path);
     const packageJsonPath = path.join(actionDir, 'package.json');
     log.debug(`Looking for package.json at: ${packageJsonPath}`);
     try {
-      accessSync(packageJsonPath);
-      const packageData: Partial<PackageJson> = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
+      const packageData: Partial<PackageJson> = JSON.parse(readFile(packageJsonPath));
       packageVersion = packageData.version;
       log.debug(`version string from target repo package.json: ${packageVersion ?? 'not found'}`);
     } catch (error) {

If you make this change, you can also remove the accessSync import from line 2:

-import { accessSync, readFileSync } from 'node:fs';
+import { readFileSync } from 'node:fs';
🤖 Prompt for AI Agents
In `@src/helpers.ts` around lines 375 - 387, Remove the redundant accessSync usage
and switch to the existing readFile helper: replace the try block that calls
accessSync and readFileSync(packageJsonPath) with a try that calls
readFile(packageJsonPath) and JSON.parse its result to set packageVersion
(preserving the same log.debug messages and the catch fallback to
process.env.npm_package_version), and then remove the unused accessSync import;
update references to packageJsonPath, packageVersion, readFile, log.debug, and
process.env.npm_package_version accordingly.

- Update remoteGitUrlPattern to capture repo name with or without .git suffix
- Strip .git suffix in repositoryFinder when processing git config
- Fix integration test to check for any markdown header level (# or ##)
- Fix non-null assertions to use proper type guards with block statements
- Update tests to reflect new regex behavior

The actions/checkout action may create .git/config entries without the
.git suffix on the remote URL. This caused auto-detection to fail when
the URL was https://github.com/owner/repo instead of
https://github.com/owner/repo.git

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Copilot AI review requested due to automatic review settings February 4, 2026 01:45
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR replaces ESLint with Biome across the project, tightens Node/tooling requirements, and significantly improves repository/version auto-detection for external-repo scenarios, with corresponding integration tests and Claude agent configuration/docs.

Changes:

  • Switches linting/formatting to Biome (config in biome.json), updates npm scripts, lint-staged, and CI workflows to run Biome checks and reviewdog with reviewdog-action-biome.
  • Improves repo and version detection logic in src/helpers.ts and src/inputs.ts (preferring target repo .git/config and package.json, handling external repos correctly) and adds a large integration-external-repo.test.ts plus stronger CI integration tests to validate owner/repo/version auto-detection.
  • Applies type-only imports and small type-safety/clarity tweaks across various modules and tests (e.g., ReadmeSection and Inputs imports, SVGEditor, LogTask, constants), and adds Claude skills/agents and documentation files to standardize workflows.

Reviewed changes

Copilot reviewed 50 out of 51 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/svg-editor.mts Makes initSVG/generateSvgImage synchronous (they never used real async work) and tightens type imports for svgdom; behavior remains the same for internal callers.
src/sections/*.ts (usage/title/outputs/inputs/description/contents/badges/index) Converts ReadmeSection imports to type-only, adds explicit LogTask type on the shared logger, and changes section dispatcher to return await the async updaters (no semantic change).
src/sections/update-branding.ts Uses type import for ReadmeSection, adds a blank line for Biome formatting, and makes generateImgMarkup’s width parameter explicitly typed with a default; logic unchanged.
src/save.ts Switches Inputs and LogTask imports to type-only, which is safe since this module only uses them as parameter types, not values.
src/readme-generator.ts Uses type-only imports for ReadmeSection, Inputs, and LogTask; all usage is in type positions (fields/parameters), so runtime behavior is unchanged.
src/readme-editor.ts Expands updateSection signature across multiple lines, makes addNewlines argument explicitly typed with default, and aligns with Biome/Prettier style; behavior identical.
src/prettier.ts Adds explicit LogTask type for the log instance, switches to return await format(...) (semantically equivalent), and makes wrapDescription’s prefix parameter explicitly typed plus a clearer early return; no behavioral regressions.
src/logtask/index.ts Adds explicit typeof chalkPkg typing to the destructuring, pins LogGroup enum numeric values (same as previous implicit values), and tightens method parameter types/defaults; logging semantics remain the same.
src/inputs.ts Uses type-only import for Input, reorders ConfigKeys import, drops __filename/__dirname in favor of import.meta.dirname, tweaks transformGitHubInputsToArgv to ignore empty owner/repo so auto-detection can work, and in loadDefaultConfig passes a baseDir (derived from paths:action) into repositoryFinder for more accurate detection of external repos.
src/helpers.ts Removes fileURLToPath/__dirname polyfills, improves defensive checks in small helpers, overhauls remoteGitUrlPattern (now capturing repo with optional .git suffix) and repositoryFinder (prioritizing .git/config in a provided baseDir, then context, GITHUB_REPOSITORY, then CWD .git/config, stripping .git from repo), and significantly improves getCurrentVersionString by reading package.json from the target repo directory with sensible defaults and prefix handling.
src/constants.ts Adds explicit Set<string> typing to GITHUB_ACTIONS_OMITTED_ICONS and GITHUB_ACTIONS_BRANDING_ICONS; functional behavior unchanged.
src/Action.ts Refines Runs* types by dropping unnecessary string-literal quotes, extends Output with optional value, and rewrites Action.validate to accept unknown and perform safer structural checks before use (but see note below about the predicate return type).
package.json Replaces ESLint-related scripts and devDependencies with Biome equivalents (format/lint/check commands, lint-staged hooks), adds @biomejs/biome, updates lint-staged patterns to use Biome for TS and Prettier for md/yaml/sh, and tightens engines.node to >=20.11.0 <26.0.0.
eslint.config.mjs Entire ESLint flat config is removed, consistent with the move to Biome-only linting.
biome.json New comprehensive Biome configuration enabling formatter and linter, with project-specific includes/excludes, rule levels (including nursery rules and relaxed rules for tests), and per-language/per-extension formatting rules.
__tests__/update-contents.test.ts, __tests__/readme-generator.test.ts, __tests__/inputs.test.ts, __tests__/helpers.test.ts, __tests__/constants.test.ts, __tests__/action.test.ts Adjust tests to use type-only imports where appropriate, switch to import.meta.dirname in a couple of places, and add a // biome-ignore annotation for an intentional delete process.env usage; behavior of tests remains the same.
__tests__/integration-issue-335.test.ts Updates comments to reference import.meta.dirname instead of __dirname in the explanation of how collectAllDefaultValuesFromAction locates this tool’s action.yml.
__tests__/integration-external-repo.test.ts New, extensive integration suite modeling many external-repo scenarios (different combinations of OWNER/REPO inputs, GITHUB_REPOSITORY, target .git/config, subdirectory layouts, shallow clones, missing package.json, precedence rules), verifying that owner/repo/version auto-detection now yields owner/repo@vX.Y.Z and that invalid patterns (/@undefined, /@v0.0.0, etc.) are rejected.
.prettierrc.cjs Tweaks Prettier config toward Biome-aligned style (quoteProps: 'as-needed', JSON print width reduced to 320) while still keeping Prettier around for runtime YAML/Markdown formatting.
.github/workflows/test.yml Installs Biome via biomejs/setup-biome@v2, runs biome check ./src/ ./__tests__/ before tests, and otherwise keeps the existing test/coverage/build/docs steps.
.github/workflows/push_code_linting.yml Renames lint job to biome_annotation, sets up Biome and runs biome lint, keeps markdownlint, and replaces reviewdog/action-eslint with mongolyy/reviewdog-action-biome@v1 using GITHUB_TOKEN and stricter failure-on-error behavior.
.github/workflows/integration-test.yml Clarifies that integration tests intentionally do not pass owner/repo/version inputs (to validate auto-detection) and adds a new step to parse the usage line from the generated README, asserting correct owner/repo and rejecting placeholder/invalid versions (e.g., v0.0.0, undefined, latest).
.github/actions/setup-node/action.yml Bumps the locally vendored actions/setup-node composite action to use actions/setup-node@v6, which matches modern Node 20.x support.
.editorconfig Changes special sections for dist, build, and minified files from ignore to unset/insert_final_newline = unset, better aligning with editorconfig semantics without impacting source formatting.
.claude/** (skills, refs, docs) Adds a substantial Claude Code skills/agents ecosystem (holistic linting, agent creator, hooks, plugin and skills references, smells TODOs, etc.) to standardize multi-agent workflows around linting, architecture review, delegation, and tooling, but these are tooling/docs only and do not affect the runtime library/API.
.claude/agents/context-gathering.md, code-review.md, linting-root-cause-resolver.md, post-linting-architecture-reviewer.md New Claude agents for context gathering, code review, lint-root-cause resolution, and post-lint architecture review; again, these don’t impact the Node tool itself but establish standardized review flows.
.claude/CLAUDE.md Project-level Claude config that bans the generic Explore agent in favor of the new context-gathering agent.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@__tests__/integration-external-repo.test.ts`:
- Around line 49-69: The test suite mutates global process state via
beforeEach/afterEach (process.cwd(), process.env, vi.unstubAllEnvs(), tempDir)
and must be isolated; either update vitest.config.ts to set pool: 'forks' or
pool: 'single-file' to prevent parallel execution, or refactor the test to avoid
mutating globals by mocking process.cwd() and using process.env mocks/local
copies instead of assigning process.env directly; apply the chosen change and
rerun the suite to ensure no cross-file interference.

Comment on lines +49 to +69
beforeEach(() => {
// Store the original working directory and environment
originalCwd = process.cwd();
originalEnv = { ...process.env };

// Create a temporary directory to simulate an external user's project
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gha-external-repo-test-'));
});

afterEach(() => {
// Restore the original working directory
process.chdir(originalCwd);

// Restore environment variables
process.env = originalEnv;
vi.unstubAllEnvs();

// Clean up the temporary directory if it exists
if (tempDir && fs.existsSync(tempDir)) {
fs.rmSync(tempDir, { recursive: true, force: true });
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find and inspect Vitest configuration
echo "=== Finding Vitest config files ==="
fd -a -t f 'vitest.config.*' . 2>/dev/null || echo "No vitest.config.* found with fd"

echo -e "\n=== Searching for vitest in package.json ==="
cat package.json 2>/dev/null | grep -A 10 -B 2 'vitest' || echo "No vitest found in package.json"

echo -e "\n=== Checking for vite/vitest config patterns ==="
find . -maxdepth 2 -name '*.config.*' -type f 2>/dev/null | head -20

Repository: bitflight-devops/github-action-readme-generator

Length of output: 1426


🏁 Script executed:

#!/bin/bash
# Inspect the actual test file for isolation patterns
echo "=== Reading test file setup and teardown ==="
cat -n __tests__/integration-external-repo.test.ts | head -80

echo -e "\n=== Checking for vitest pool configuration in the file ==="
grep -n 'pool\|threads\|forked\|isolate\|beforeAll\|afterAll' __tests__/integration-external-repo.test.ts

Repository: bitflight-devops/github-action-readme-generator

Length of output: 3700


🏁 Script executed:

#!/bin/bash
# Check the __tests__ directory structure to verify mirror guideline
echo "=== Checking __tests__ directory structure ==="
find __tests__ -type f -name '*.test.ts' | head -20

echo -e "\n=== Checking src directory structure for comparison ==="
find src -type f -name '*.ts' -o -name '*.tsx' | head -20

Repository: bitflight-devops/github-action-readme-generator

Length of output: 1011


🏁 Script executed:

#!/bin/bash
echo "=== Reading vitest.config.ts ==="
cat -n vitest.config.ts

Repository: bitflight-devops/github-action-readme-generator

Length of output: 742


Isolate this test suite from parallel execution due to global process state mutations.

This test suite mutates process.cwd() and process.env in beforeEach/afterEach. The Vitest config does not explicitly set a pool option, so it defaults to pool: 'threads' (v4.0.18), running tests in parallel across threads. This creates a race condition risk—other test files executing concurrently may observe intermediate process state changes during test execution, causing flakiness.

Add explicit isolation to vitest.config.ts:

  • pool: 'forks' (separate processes, full isolation), or
  • pool: 'single-file' (isolate per test file, reasonable for this suite)

Alternatively, refactor the test to avoid mutating process-wide state by using mocking for process.cwd() and environment access where feasible.

🤖 Prompt for AI Agents
In `@__tests__/integration-external-repo.test.ts` around lines 49 - 69, The test
suite mutates global process state via beforeEach/afterEach (process.cwd(),
process.env, vi.unstubAllEnvs(), tempDir) and must be isolated; either update
vitest.config.ts to set pool: 'forks' or pool: 'single-file' to prevent parallel
execution, or refactor the test to avoid mutating globals by mocking
process.cwd() and using process.env mocks/local copies instead of assigning
process.env directly; apply the chosen change and rerun the suite to ensure no
cross-file interference.

GitHub Actions are versioned using git tags (uses: owner/repo@v1.2.3),
not package.json. The previous implementation incorrectly prioritized
package.json which only works for npm-based actions.

New priority order for version detection:
1. version_override config option (explicit user preference)
2. Git tags from target directory (primary for GitHub Actions)
3. package.json from target directory (for npm-based actions)
4. npm_package_version environment variable (backward compatibility)
5. Default to 0.0.0

This fixes version auto-detection for typical GitHub Actions that use
git tags for versioning but don't have package.json files.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
@Jamie-BitFlight Jamie-BitFlight force-pushed the claude/update-actions-biome-uXcwR branch from 8fdef0f to e5c9434 Compare February 4, 2026 01:56
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/helpers.ts`:
- Around line 201-206: The debug call currently prints the entire .git/config
contents (variable fileContent) which can leak credentials; instead, remove the
raw fileContent from logging and only log the gitConfigPath and a redacted
remote URL if present. Specifically, in the baseDir block around
gitConfigPath/readFile/remoteGitUrlPattern.exec, stop passing fileContent to
log.debug, run remoteGitUrlPattern.exec(fileContent) and, if it matches, redact
any auth/token segment (e.g., replace user:pass@ or token@ with *****@) and log
the redacted URL; otherwise log only the config path and a note that no remote
URL was found. Ensure you update the log.debug call near readFile to reference
gitConfigPath and the redacted URL variable (not the full fileContent).
🧹 Nitpick comments (1)
src/helpers.ts (1)

377-394: Verify git-tag detection command portability.

The command relies on shell redirection and head, which can break on non-Unix runners. If Windows runners are supported, consider splitting into two git calls and parsing output in Node.

🔧 Portable alternative (no shell pipes)
-      const gitVersion = execSync(
-        'git describe --tags --abbrev=0 2>/dev/null || git tag -l "v*" --sort=-v:refname | head -1',
-        {
-          cwd: actionDir,
-          encoding: 'utf8',
-        },
-      ).trim();
+      let gitVersion = '';
+      try {
+        gitVersion = execSync('git describe --tags --abbrev=0', {
+          cwd: actionDir,
+          encoding: 'utf8',
+        }).trim();
+      } catch {
+        const tags = execSync('git tag -l "v*" --sort=-v:refname', {
+          cwd: actionDir,
+          encoding: 'utf8',
+        }).trim();
+        gitVersion = tags.split(/\r?\n/)[0] ?? '';
+      }

Comment on lines +201 to +206
if (baseDir) {
try {
const gitConfigPath = path.join(baseDir, '.git', 'config');
const fileContent = readFile(gitConfigPath);
log.debug(`loading ${gitConfigPath}:\n***\n${fileContent}\n***`);
const results = remoteGitUrlPattern.exec(fileContent);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Avoid logging full .git/config contents.

Debug logs can leak credentials if the remote URL embeds tokens. Log only the path or redact sensitive parts.

🔒 Proposed change
-      log.debug(`loading ${gitConfigPath}:\n***\n${fileContent}\n***`);
+      log.debug(`loading ${gitConfigPath}`);
🤖 Prompt for AI Agents
In `@src/helpers.ts` around lines 201 - 206, The debug call currently prints the
entire .git/config contents (variable fileContent) which can leak credentials;
instead, remove the raw fileContent from logging and only log the gitConfigPath
and a redacted remote URL if present. Specifically, in the baseDir block around
gitConfigPath/readFile/remoteGitUrlPattern.exec, stop passing fileContent to
log.debug, run remoteGitUrlPattern.exec(fileContent) and, if it matches, redact
any auth/token segment (e.g., replace user:pass@ or token@ with *****@) and log
the redacted URL; otherwise log only the config path and a note that no remote
URL was found. Ensure you update the log.debug call near readFile to reference
gitConfigPath and the redacted URL variable (not the full fileContent).

Add TODO for implementing configurable version source selection:
- git-tag (default)
- git-branch
- git-sha
- package.json
- explicit override

Also add session management notes for Claude about TODO handling.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
The actions/checkout does a shallow clone by default which doesn't
include git tags. Since version detection now prioritizes git tags,
we need to explicitly fetch them with fetch-tags: true.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
Remove head -50 truncation so the complete diff between original
and generated README is visible in CI logs.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
The rowHeader() function was changed from <b><code> to just <code>
in commit 0451f2c. Add TODO to consider restoring the original
bold formatting behavior.

https://claude.ai/code/session_014MQ1RezhSBEvLzTaLsKiFP
@Jamie-BitFlight Jamie-BitFlight merged commit a373c00 into main Feb 4, 2026
10 checks passed
@Jamie-BitFlight Jamie-BitFlight deleted the claude/update-actions-biome-uXcwR branch February 4, 2026 02:55
@Jamie-BitFlight
Copy link
Contributor Author

🎉 This PR is included in version 1.9.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

@Jamie-BitFlight Jamie-BitFlight added the released This issue/pull request has been released. label Feb 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released This issue/pull request has been released.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants