Skip to content

Tests and releases#84

Merged
cdeutsch merged 7 commits intomasterfrom
tests-and-releases
Apr 7, 2026
Merged

Tests and releases#84
cdeutsch merged 7 commits intomasterfrom
tests-and-releases

Conversation

@cdeutsch
Copy link
Copy Markdown
Owner

@cdeutsch cdeutsch commented Mar 20, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Automated release publishing and dependency updates via GitHub Actions.
  • Chores

    • Updated Node.js minimum version requirement to 18+.
    • Modernized test infrastructure and build configuration.
    • Enhanced documentation for release and maintenance procedures.

Here’s what was done to clear **npm audit** and keep the repo building.

### Dependency & security changes
- **Ran `npm audit fix`** (already applied ~37 fixes in the lockfile before the larger edits).
- **Removed Babel 6** (`babel-core`, `babel-runtime`) and **deprecated Rollup plugins**; added **`@babel/core`**, **`@rollup/plugin-babel`**, **`@rollup/plugin-commonjs`**, **`@rollup/plugin-node-resolve`**.
- **Rollup `^2.64` → `^4.59`** and **`rollup.config.mjs`** (ESM config, reads `package.json` with `fs` so Node 22+ JSON imports aren’t required).
- **Jest `^27` → `^29`**, **`ts-jest` → `^29`**, **`@types/jest` → `^29`** (fixes the old **jsdom / `@tootallnate/once`** chain).
- **Dropped unused `rollup-plugin-sass`** (it pulled an old **sass → chokidar** tree with noisy audit issues).
- **`engines.node` → `>=18`** (required for Rollup 4).
- **`overrides`** for **`lodash`**, **`tmp`**, **`trim-newlines`** (fixes **`commitizen` / `inquirer` / `meow`** paths without breaking **trash-cli** — `trim-newlines@5` broke **`meow`**).
- **`cheerio` → `1.0.0-rc.12`** via **`overrides`** so **Enzyme 3** still resolves **`cheerio/lib/utils`** (npm was hoisting **cheerio@1.2.0**, which removed that path).
- **`.babelrc`**: `@babel/plugin-proposal-class-properties` → **`@babel/plugin-transform-class-properties`** (and matching **devDependency**).

### `FormsProvider.tsx`
Your working tree had **`FormsProvider.tsx` replaced by a few comment lines**, which broke the **Rollup** build (`FormsContext` missing). It was **restored from `git HEAD`**. If you still want that personal note, keep it outside this file or re-apply it after pulling the real component back from version control.

### Current status
- **`npm audit`**: **0 vulnerabilities**
- **`npm test`** and **`npm run build`**: **pass**

If you want the Tiffany lines back *inside* the repo, say where (e.g. `README` or a private note file) and we can add them without touching the library entrypoints.
…supported.

Moves publishing and changelog tagging to semantic-release via GitHub Actions, adds Dependabot for npm (`/` and `demo/`) and for GitHub Actions, and documents setup in `RELEASING.md` with a pointer from `README.md`.

Swaps Enzyme/commitizen/standard-version for React Testing Library (`@testing-library/react`, `jest-dom`, `user-event`), turns on `jsdom` in `jest.config.js`, and replaces the placeholder `hello-world` test with `validations.test.ts`, `FormsProvider.engine.test.ts`, and `ClassyForm.test.tsx`. Drops the old `npm overrides` block from `package.json`.

Adds `.github/workflows/release.yml`, `.github/dependabot.yml`, and `.releaserc.json`; trims `.npmignore` for release-related paths. Staged `package-lock.json` reflects the dependency churn. Includes a small change to `.vscode/settings.json` (demo folder exclude).
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 20, 2026

📝 Walkthrough

Walkthrough

This pull request modernizes the project's build tooling, CI/CD, and testing infrastructure. Changes include migrating from Enzyme to Testing Library, implementing automated dependency updates via Dependabot and release automation via semantic-release, updating Jest configuration with jsdom environment, replacing Rollup configuration with an ES module variant, updating Node.js engine requirements from >=8.9 to >=18, and removing legacy Babel/build dependencies in favor of modern alternatives.

Changes

Cohort / File(s) Summary
Babel & Build Configuration
.babelrc, rollup.config.js, rollup.config.mjs
Updated Babel plugin from proposal to transform variant; removed legacy Rollup config; added new .mjs Rollup config with Node module resolution, CommonJS interop, and Babel transpilation for TypeScript entries.
CI/CD & Release Automation
.github/dependabot.yml, .github/workflows/release.yml, .releaserc.json, .npmignore
Added Dependabot configuration for automated monthly dependency updates; added GitHub Actions release workflow running on master pushes with Node.js 22.14; added semantic-release config for CHANGELOG/version updates and npm publishing; updated npmignore to exclude release config.
Package & Dependencies
package.json
Removed release/version scripts and commitizen config; updated Node.js engine to >=18; removed Enzyme/legacy Babel deps; added semantic-release and Testing Library packages; upgraded Jest and ts-jest; switched Rollup plugins to scoped @rollup variants.
Testing Configuration & Framework Migration
jest.config.js, src/setupTests.ts, src/__tests__/hello-world.test.tsx
Changed test discovery from testRegex to testMatch; added testEnvironment: 'jsdom'; switched post-environment setup to setupFilesAfterEnv; removed Enzyme configuration and raf/polyfill; added @testing-library/jest-dom; deleted legacy Enzyme test file.
Test Coverage Additions
src/ClassyForm.test.tsx, src/FormsProvider.engine.test.ts, src/validations.test.ts
Added comprehensive test suites for ClassyForm component (101 lines), FormsProvider helper functions (75 lines), and validators module (106 lines) using Testing Library and Jest patterns.
Documentation
README.md, RELEASING.md
Added "Releases & maintenance" section to README documenting Dependabot and semantic-release workflows; created detailed RELEASING.md with setup instructions, Trusted Publishing configuration, conventional commit requirements, and fallback guidance.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A Warren's Modernization

Enzyme fades, Testing Library blooms so bright,
Semantic-release hops through the master night,
Dependabot tends the dependencies with care,
Rollup's new config dances through the air,
Node eighteen and onward—our burrow's fresh and fair! 🌿

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 'Tests and releases' directly captures the main changes: addition of comprehensive test suites and automated release infrastructure (semantic-release, Dependabot, GitHub Actions workflow).

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tests-and-releases

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

Tip

CodeRabbit can suggest fixes for GitHub Check annotations.

Configure the reviews.tools.github-checks setting to adjust the time to wait for GitHub Checks to complete.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 20, 2026

Greptile Summary

This PR modernizes the test and release infrastructure for classy-forms: it replaces the old Enzyme-based tests with @testing-library/react, upgrades to Jest 29 + ts-jest 29, migrates the Rollup build to use modern @rollup/plugin-* packages, introduces automated npm releases via semantic-release with npm Trusted Publishing (OIDC), and adds Dependabot for automated dependency PRs.

Key changes:

  • Old Enzyme / enzyme-adapter-react-16 tests removed; new integration tests in ClassyForm.test.tsx and unit tests in FormsProvider.engine.test.ts and validations.test.ts added with good coverage.
  • jest.config.js updated: jsdom test environment, setupFilesAfterEnv pointing to @testing-library/jest-dom, testMatch expanded to cover both __tests__/ directories and *.test.* files.
  • rollup.config.js (Rollup 2, deprecated plugins) replaced by rollup.config.mjs (Rollup 4, @rollup/plugin-*).
  • @babel/proposal-class-properties renamed to the canonical @babel/plugin-transform-class-properties.
  • .github/workflows/release.yml added: runs tests and build then semantic-release on every push to master, using OIDC Trusted Publishing so no long-lived NPM_TOKEN is stored in GitHub.
  • .github/dependabot.yml added for monthly npm (root + demo/) and GitHub Actions updates.
  • Notable gap: There is no dedicated CI workflow for pull requests. Tests currently only run as part of the release job on master pushes, so regressions introduced via a PR are not caught until after merge.

Confidence Score: 3/5

  • Safe to merge for functionality, but the missing PR CI workflow means future regressions won't be caught before hitting master.
  • The code changes are sound — tests are well-written, the rollup migration is clean, and the semantic-release/OIDC setup follows best practices. The confidence reduction is entirely due to the absence of a pull-request CI workflow, which means this PR and all future PRs land on master without automated test validation.
  • .github/workflows/release.yml — no PR trigger; a companion ci.yml should be added.

Important Files Changed

Filename Overview
.github/workflows/release.yml New release workflow using semantic-release + npm Trusted Publishing (OIDC). Missing a separate PR/CI check workflow — tests only run on master pushes, not on pull requests.
.releaserc.json Correct semantic-release configuration with standard plugin ordering; commits package.json, package-lock.json, and CHANGELOG.md on release.
src/ClassyForm.test.tsx New integration tests using @testing-library/react replacing the old Enzyme-based tests; covers submit, validation prevention, and form reset.
src/FormsProvider.engine.test.ts New unit tests for internal helpers (initializeFormFields, getFormFieldConfig, isValid, validateFormFields); good coverage of core engine logic.
src/validations.test.ts New unit tests for the validations module; covers all major validators (required, email, regexp, equality, min/max length).
rollup.config.mjs Old rollup.config.js replaced with ESM-native rollup.config.mjs using modern @rollup/plugin-* packages; external field correctly derived from package.json dependencies.
jest.config.js Migrated from ts-jest v27 + raf/polyfill + Enzyme to ts-jest v29 + jsdom environment; testMatch expanded to pick up *.test.[jt]s?(x) files alongside tests directories.
package.json Dependencies modernized (jest 29, ts-jest 29, @rollup/plugin-*, @testing-library, semantic-release suite); Enzyme and standard-version removed; node engine bumped to >=18.
.babelrc Renamed deprecated @babel/proposal-class-properties to @babel/plugin-transform-class-properties; rest of config unchanged.

Sequence Diagram

sequenceDiagram
    participant Dev as Developer
    participant GH as GitHub (master push)
    participant CI as release.yml job
    participant SR as semantic-release
    participant npm as npmjs.com (OIDC)
    participant Repo as Git repo

    Dev->>GH: git push master (Conventional Commit)
    GH->>CI: Trigger release workflow
    CI->>CI: npm ci
    CI->>CI: npm test
    CI->>CI: npm run build
    CI->>SR: npx semantic-release
    SR->>SR: Analyze commits → determine next semver
    SR->>Repo: Update CHANGELOG.md, package.json, package-lock.json
    SR->>npm: Publish via OIDC (no NPM_TOKEN)
    SR->>GH: Create GitHub Release + tag
    SR->>Repo: Push release commit [skip ci]
Loading

Comments Outside Diff (1)

  1. package.json, line 14 (link)

    P2 Consider pinning the rollup config filename explicitly

    rollup -c searches for config files in a defined order (rollup.config.mjs, rollup.config.cjs, rollup.config.js, etc.). Since the repo now only ships rollup.config.mjs, the lookup is unambiguous in practice. However, making the filename explicit removes any future ambiguity if another config file is accidentally added:

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Last reviewed commit: "Attempt to switch re..."

Comment on lines +5 to +8
on:
push:
branches:
- master
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 No CI workflow for pull requests

The only workflow in this repo is release.yml, which triggers exclusively on pushes to master. This means tests (npm test) and the build (npm run build) are never validated on pull requests before they are merged.

If a PR introduces a test regression or a broken build, it will only be caught during the release run — after the code is already on master — causing the release to fail.

Consider adding a lightweight CI workflow, for example:

# .github/workflows/ci.yml
name: CI

on:
  pull_request:
  push:
    branches: [master]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22.14'
          cache: npm
      - run: npm ci
      - run: npm test
      - run: npm run build

The release.yml job could then be simplified to skip the test/build steps (or keep them as a safety net), since CI already guards the branch.

Copy link
Copy Markdown

@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: 3

🧹 Nitpick comments (4)
rollup.config.mjs (1)

10-10: Add a fail-fast guard for package.json output fields.

If main or module is missing, Rollup errors later and less clearly. Validate once up front.

Proposed patch
 const __dirname = dirname(fileURLToPath(import.meta.url));
 const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8'));
+if (!pkg.main || !pkg.module) {
+  throw new Error("package.json must define both 'main' and 'module' fields");
+}

Also applies to: 29-37

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rollup.config.mjs` at line 10, Add a fail-fast guard after parsing
package.json (the const pkg = JSON.parse(readFileSync(join(__dirname,
'package.json'), 'utf8')) line) to validate that pkg.main and pkg.module (the
output fields used later in the rollup config) are present and non-empty; if
either is missing, throw or log a clear error and exit (so Rollup doesn't fail
later with an opaque error). Also add the same check/guard covering the code
paths around the output construction (the block referenced in lines 29-37) so
both CJS and ESM outputs are validated up-front.
src/ClassyForm.test.tsx (1)

37-37: Prefer user-level submit interaction over direct fireEvent.submit.

Testing Library recommends using real interactions—clicking a submit button through userEvent better reflects user behavior and reduces coupling to DOM queries. This also aligns with existing patterns in the test suite (e.g., line 97).

Proposed patch
  it('calls onSubmit when form is valid', async () => {
    const user = userEvent.setup();
    const onSubmit = jest.fn();

    const { container } = render(
      <ClassyForm<DemoForm>
        formFieldConfigs={[{ name: 'title', required: true }]}
        onSubmit={onSubmit}
      >
        {({ formFields }) => (
          <>
            <label htmlFor="title">Title</label>
            <input
              id="title"
              value={formFields.title.value as string}
              onChange={formFields.title.onChange}
            />
            <button type="submit">Save</button>
          </>
        )}
      </ClassyForm>
    );

    await user.type(screen.getByLabelText('Title'), 'My title');
-    fireEvent.submit(container.querySelector('form')!);
+    await user.click(screen.getByRole('button', { name: 'Save' }));

    expect(onSubmit).toHaveBeenCalledTimes(1);
    const [event, submittedFields] = onSubmit.mock.calls[0];
    expect(event.defaultPrevented).toBe(false);
    expect(submittedFields.title.value).toBe('My title');
  });

-  it('prevents submit when invalid (required empty)', () => {
+  it('prevents submit when invalid (required empty)', async () => {
+    const user = userEvent.setup();
    const onSubmit = jest.fn();

    const { container } = render(
      <ClassyForm<DemoForm>
        formFieldConfigs={[{ name: 'title', required: true }]}
        onSubmit={onSubmit}
      >
        {({ formFields }) => (
          <>
            <label htmlFor="title">Title</label>
            <input id="title" value={formFields.title.value as string} onChange={formFields.title.onChange} />
            <button type="submit">Save</button>
          </>
        )}
      </ClassyForm>
    );

-    fireEvent.submit(container.querySelector('form')!);
+    await user.click(screen.getByRole('button', { name: 'Save' }));

    expect(onSubmit).not.toHaveBeenCalled();
  });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ClassyForm.test.tsx` at line 37, Replace the direct call to
fireEvent.submit(container.querySelector('form')!) in the ClassyForm test with a
user-level interaction: locate the form's submit button (same element used
elsewhere in this test suite) and trigger userEvent.click(submitButton) so the
test exercises real user behavior; update any imports to ensure userEvent from
'@testing-library/user-event' is used and remove the fireEvent.submit usage in
the test in src/ClassyForm.test.tsx.
jest.config.js (1)

5-7: Reference ts-jest by package name instead of a node_modules path.

The documented ts-jest config points transform at 'ts-jest' (or ['ts-jest', options]), and Jest resolves transform entries as module names or paths. Hard-coding <rootDir>/node_modules/ts-jest ties this config to one install layout for no real benefit. (kulshekhar.github.io)

♻️ Suggested change
   transform: {
-    '\\.(ts|tsx)$': '<rootDir>/node_modules/ts-jest',
+    '^.+\\.tsx?$': 'ts-jest',
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@jest.config.js` around lines 5 - 7, Update the Jest transform entry to
reference the ts-jest package by module name instead of a hard-coded
node_modules path: in the transform object (the key '\\.(ts|tsx)$') replace
'<rootDir>/node_modules/ts-jest' with 'ts-jest' (or ['ts-jest', options] if you
need to pass options) so Jest resolves the transformer via package name rather
than a fixed install layout.
package.json (1)

53-53: Avoid pinning semantic-release’s bundled plugins separately.

semantic-release already bundles the default analyzer/notes/npm/GitHub plugins, and the npm plugin docs explicitly warn that re-declaring bundled plugins as direct dependencies can create upgrade conflicts. Keeping only the extra plugins here would reduce duplicate version management. (semantic-release.gitbook.io)

♻️ Suggested cleanup
     "@semantic-release/changelog": "^6.0.3",
-    "@semantic-release/commit-analyzer": "^13.0.0",
     "@semantic-release/git": "^10.0.1",
-    "@semantic-release/github": "^11.0.0",
-    "@semantic-release/npm": "^13.1.5",
-    "@semantic-release/release-notes-generator": "^14.0.1",

Also applies to: 55-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 53, Remove the explicitly listed bundled
semantic-release plugins from package.json (e.g.
"@semantic-release/commit-analyzer" and the other semantic-release entries
mentioned at lines 55-57) so you don't pin bundled dependencies; keep only
non-bundled/extra semantic-release plugins if any, and rely on the
semantic-release package to provide its default analyzer/notes/npm/GitHub
plugins to avoid duplicate version management and upgrade conflicts.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release.yml:
- Around line 26-32: The workflow currently uses the "Setup Node.js" step but
doesn't guarantee npm >= 11.5.1; add a new step right after the Setup Node.js
step to ensure npm meets Trusted Publishing by activating/upgrading npm (for
example use Corepack to prepare/activate npm@>=11.5.1 or run a targeted npm
install) so publishing won't fail; reference the "Setup Node.js" step and add a
follow-up step that runs the npm upgrade/activation command before any publish
actions.

In `@RELEASING.md`:
- Around line 51-52: Update the sentence about Dependabot so it clarifies that
semantic-release's patch release behavior depends on the merge strategy
preserving the PR title; specifically, change the line that references
Dependabot using "fix(deps):" to say that when the merge strategy preserves that
title as the final commit subject on master (for example via squash or rebase)
those dependency updates typically produce a patch release, since GitHub's
default merge commit ("Merge pull request #...") will not match conventional
commit rules.

In `@src/FormsProvider.engine.test.ts`:
- Around line 66-73: Update the test to exercise the invalid→valid transition on
the same FormFields object: first create configs and a formFields via
initializeFormFields, set formFields.title.value to an invalid value (e.g.
empty) and call validateFormFields(configs) to generate errors, then mutate
formFields.title.value to a valid value ('hello') and call
validateFormFields(formFields, configs, true) again and assert result.allValid
is true and that formFields.title.errors is cleared and
formFields.title.hasError is false; this ensures validateFormFields properly
mutates/clears state on the same FormFields instance rather than relying on a
fresh object.

---

Nitpick comments:
In `@jest.config.js`:
- Around line 5-7: Update the Jest transform entry to reference the ts-jest
package by module name instead of a hard-coded node_modules path: in the
transform object (the key '\\.(ts|tsx)$') replace
'<rootDir>/node_modules/ts-jest' with 'ts-jest' (or ['ts-jest', options] if you
need to pass options) so Jest resolves the transformer via package name rather
than a fixed install layout.

In `@package.json`:
- Line 53: Remove the explicitly listed bundled semantic-release plugins from
package.json (e.g. "@semantic-release/commit-analyzer" and the other
semantic-release entries mentioned at lines 55-57) so you don't pin bundled
dependencies; keep only non-bundled/extra semantic-release plugins if any, and
rely on the semantic-release package to provide its default
analyzer/notes/npm/GitHub plugins to avoid duplicate version management and
upgrade conflicts.

In `@rollup.config.mjs`:
- Line 10: Add a fail-fast guard after parsing package.json (the const pkg =
JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8')) line) to
validate that pkg.main and pkg.module (the output fields used later in the
rollup config) are present and non-empty; if either is missing, throw or log a
clear error and exit (so Rollup doesn't fail later with an opaque error). Also
add the same check/guard covering the code paths around the output construction
(the block referenced in lines 29-37) so both CJS and ESM outputs are validated
up-front.

In `@src/ClassyForm.test.tsx`:
- Line 37: Replace the direct call to
fireEvent.submit(container.querySelector('form')!) in the ClassyForm test with a
user-level interaction: locate the form's submit button (same element used
elsewhere in this test suite) and trigger userEvent.click(submitButton) so the
test exercises real user behavior; update any imports to ensure userEvent from
'@testing-library/user-event' is used and remove the fireEvent.submit usage in
the test in src/ClassyForm.test.tsx.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5578caf3-f78a-4e0c-b7a1-9097fbb6a028

📥 Commits

Reviewing files that changed from the base of the PR and between 8f578e5 and 8b2d643.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • src/__tests__/__snapshots__/hello-world.test.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (16)
  • .babelrc
  • .github/dependabot.yml
  • .github/workflows/release.yml
  • .npmignore
  • .releaserc.json
  • README.md
  • RELEASING.md
  • jest.config.js
  • package.json
  • rollup.config.js
  • rollup.config.mjs
  • src/ClassyForm.test.tsx
  • src/FormsProvider.engine.test.ts
  • src/__tests__/hello-world.test.tsx
  • src/setupTests.ts
  • src/validations.test.ts
💤 Files with no reviewable changes (2)
  • rollup.config.js
  • src/tests/hello-world.test.tsx

Comment on lines +26 to +32
# Trusted publishing: npm CLI ≥ 11.5.1 and Node ≥ 22.14.0 (see npm docs). @semantic-release/npm 13 aligns with that range.
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.14'
cache: npm
registry-url: https://registry.npmjs.org
Copy link
Copy Markdown

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 22.14.0 npm version bundled

💡 Result:

Node.js v22.14.0 bundles npm v10.9.2. [1]


🌐 Web query:

npm Trusted Publishing requirements minimum npm version

💡 Result:

For npm Trusted Publishing, the minimum npm CLI version is 11.5.1 (npm says “11.5.1 or later”). [1]

Related: if you’re using the npm trust CLI commands to manage trusted publishers, npm requires npm@11.10.0 or above. [2]

Sources:
[1] npm Docs — “Trusted publishing for npm packages”
[2] npm Docs — “npm-trust” command documentation


Pin an npm version that satisfies Trusted Publishing.

npm Trusted Publishing requires npm CLI >=11.5.1, but Node 22.14.0 bundles npm 10.9.2. The inline comment suggests the requirements are covered, but the publish step will fail because the Node version alone does not guarantee the minimum npm version.

🔧 Fix
       - name: Setup Node.js
         uses: actions/setup-node@v4
         with:
           node-version: '22.14'
           cache: npm
           registry-url: https://registry.npmjs.org
+
+      - name: Upgrade npm for Trusted Publishing
+        run: npm install -g npm@^11.5.1
📝 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
# Trusted publishing: npm CLI ≥ 11.5.1 and Node ≥ 22.14.0 (see npm docs). @semantic-release/npm 13 aligns with that range.
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.14'
cache: npm
registry-url: https://registry.npmjs.org
# Trusted publishing: npm CLI ≥ 11.5.1 and Node ≥ 22.14.0 (see npm docs). `@semantic-release/npm` 13 aligns with that range.
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.14'
cache: npm
registry-url: https://registry.npmjs.org
- name: Upgrade npm for Trusted Publishing
run: npm install -g npm@^11.5.1
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yml around lines 26 - 32, The workflow currently
uses the "Setup Node.js" step but doesn't guarantee npm >= 11.5.1; add a new
step right after the Setup Node.js step to ensure npm meets Trusted Publishing
by activating/upgrading npm (for example use Corepack to prepare/activate
npm@>=11.5.1 or run a targeted npm install) so publishing won't fail; reference
the "Setup Node.js" step and add a follow-up step that runs the npm
upgrade/activation command before any publish actions.

Comment thread RELEASING.md Outdated
Comment on lines +51 to +52
[Dependabot](.github/dependabot.yml) opens PRs monthly for npm (root and `demo/`) and GitHub Actions. PR titles use **`fix(deps):`** so merged dependency updates typically produce a **patch** release when you merge to **`master`**.

Copy link
Copy Markdown

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:

# Check the current content of RELEASING.md around lines 51-52
wc -l RELEASING.md

Repository: cdeutsch/classy-forms

Length of output: 80


🏁 Script executed:

# Read the specific lines in question
sed -n '45,60p' RELEASING.md

Repository: cdeutsch/classy-forms

Length of output: 522


🏁 Script executed:

# Check if there's a semantic-release configuration in the repo
fd -t f "semantic-release|release-config" --hidden

Repository: cdeutsch/classy-forms

Length of output: 47


🏁 Script executed:

# Look for any .releaserc or similar config
find . -maxdepth 2 -type f \( -name ".releaserc*" -o -name "release.config.*" -o -name "package.json" \) 2>/dev/null | head -20

Repository: cdeutsch/classy-forms

Length of output: 117


🏁 Script executed:

# Check package.json for release configuration
cat package.json | grep -A 30 "release"

Repository: cdeutsch/classy-forms

Length of output: 1000


🏁 Script executed:

# Check the .releaserc.json configuration
cat .releaserc.json

Repository: cdeutsch/classy-forms

Length of output: 525


🏁 Script executed:

# Check if there's any GitHub merge strategy configuration
cat .github/dependabot.yml

Repository: cdeutsch/classy-forms

Length of output: 625


🏁 Script executed:

# Search for any documentation about merge strategy or how commits are processed
rg "merge|commit|squash" RELEASING.md

Repository: cdeutsch/classy-forms

Length of output: 1048


Clarify merge strategy dependency for Dependabot release behavior.

semantic-release determines release type from commit messages that land on master. Dependabot sets the commit prefix to fix(deps):, but this only produces a patch release if the merge strategy preserves that message as the final commit subject. With GitHub's default merge strategy, the commit becomes "Merge pull request #..." and won't match semantic-release's conventional commit rules. Squash and rebase merges preserve the fix(deps): subject.

Update the text to specify that this patch release behavior depends on merge strategy, for example: "When the merge strategy preserves that title as the final commit subject on master (via squash/rebase), those updates typically produce a patch release."

🧰 Tools
🪛 LanguageTool

[uncategorized] ~51-~51: The official name of this software platform is spelled with a capital “H”.
Context: .... | major | ### Dependabot Dependabot opens PRs monthly for n...

(GITHUB)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@RELEASING.md` around lines 51 - 52, Update the sentence about Dependabot so
it clarifies that semantic-release's patch release behavior depends on the merge
strategy preserving the PR title; specifically, change the line that references
Dependabot using "fix(deps):" to say that when the merge strategy preserves that
title as the final commit subject on master (for example via squash or rebase)
those dependency updates typically produce a patch release, since GitHub's
default merge commit ("Merge pull request #...") will not match conventional
commit rules.

Comment thread src/FormsProvider.engine.test.ts Outdated
Comment on lines +66 to +73
it('reports allValid when field satisfies required', () => {
const configs: FormFieldConfig[] = [{ name: 'title', required: true }];
const formFields: FormFields = initializeFormFields(configs);
formFields.title.value = 'hello';
const result = validateFormFields(formFields, configs, true);
expect(result.allValid).toBe(true);
expect(formFields.title.hasError).toBe(false);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Exercise the invalid→valid transition on the same formFields object.

validateFormFields mutates the existing formFields structure in place, but this case starts from a fresh valid field. A regression where a previously-invalid field keeps stale errors or hasError after the user fixes it would still pass here.

🧪 Suggested test shape
-    it('reports allValid when field satisfies required', () => {
+    it('clears required errors once the field is fixed', () => {
       const configs: FormFieldConfig[] = [{ name: 'title', required: true }];
       const formFields: FormFields = initializeFormFields(configs);
+      expect(validateFormFields(formFields, configs, true).allValid).toBe(false);
       formFields.title.value = 'hello';
       const result = validateFormFields(formFields, configs, true);
       expect(result.allValid).toBe(true);
       expect(formFields.title.hasError).toBe(false);
+      expect(formFields.title.errors).toEqual([]);
     });
📝 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
it('reports allValid when field satisfies required', () => {
const configs: FormFieldConfig[] = [{ name: 'title', required: true }];
const formFields: FormFields = initializeFormFields(configs);
formFields.title.value = 'hello';
const result = validateFormFields(formFields, configs, true);
expect(result.allValid).toBe(true);
expect(formFields.title.hasError).toBe(false);
});
it('clears required errors once the field is fixed', () => {
const configs: FormFieldConfig[] = [{ name: 'title', required: true }];
const formFields: FormFields = initializeFormFields(configs);
expect(validateFormFields(formFields, configs, true).allValid).toBe(false);
formFields.title.value = 'hello';
const result = validateFormFields(formFields, configs, true);
expect(result.allValid).toBe(true);
expect(formFields.title.hasError).toBe(false);
expect(formFields.title.errors).toEqual([]);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/FormsProvider.engine.test.ts` around lines 66 - 73, Update the test to
exercise the invalid→valid transition on the same FormFields object: first
create configs and a formFields via initializeFormFields, set
formFields.title.value to an invalid value (e.g. empty) and call
validateFormFields(configs) to generate errors, then mutate
formFields.title.value to a valid value ('hello') and call
validateFormFields(formFields, configs, true) again and assert result.allValid
is true and that formFields.title.errors is cleared and
formFields.title.hasError is false; this ensures validateFormFields properly
mutates/clears state on the same FormFields instance rather than relying on a
fresh object.

Pull requests previously had no workflow running `npm test` or `npm run build`; only `release.yml` ran on pushes to `master`, so breakages could show up late.

Adds `.github/workflows/ci.yml` (Node 22.14, `npm ci`, test, build) on `pull_request` and pushes to `master`. Documents the workflow and why the Release job still builds before publish in `RELEASING.md`.
Aligns the release workflow with npm Trusted Publishing (Node 22 still ships npm 10.x, so the global npm bump is required alongside Node ≥ 22.14), documents how Dependabot PR titles affect semantic-release when merge commits rewrite the subject, and trims duplicate semantic-release plugin pins so versions come from the main semantic-release dependency tree.

Also resolves the Jest transformer via the `ts-jest` package name, adds upfront `package.json` `main`/`module` checks in `rollup.config.mjs`, tightens `validateFormFields` coverage on a single `FormFields` instance, and switches `ClassyForm` submit assertions to `userEvent` clicks on the Save button.
@cdeutsch
Copy link
Copy Markdown
Owner Author

cdeutsch commented Mar 20, 2026

Which issues would you like to fix?

  • [Blocker] Contributors ownership column/sort uses stale ownership_percentage instead of aggregated totalOwnership
  • [Suggestion] Analytics URL search params: bSortBy / cSortBy not validated (loose strings vs API column set)
  • [Suggestion] HighlightCard: Space key activates click without preventDefault (page scroll)
  • [Suggestion] AnalyticsBranches: redundant emptyStateHeading ternary (identical strings)
  • [Suggestion] AnalyticsContributors: full merge/filter/sort/paginate client-side (scale risk)
  • [Suggestion] RepoHome: navigation RepoFileLinks missing isLoading while other sections show skeletons
  • [Nit] HighlightCard: title tooltip duplicates visible title (low value)
  • [Nit] RepoFileLinks: skeleton rows use key={idx}

@cdeutsch cdeutsch merged commit 33fde29 into master Apr 7, 2026
2 checks passed
@cdeutsch cdeutsch deleted the tests-and-releases branch April 7, 2026 16:28
@cdeutsch
Copy link
Copy Markdown
Owner Author

cdeutsch commented Apr 8, 2026

🎉 This PR is included in version 3.1.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant