Skip to content

fix(web): handle the two unawaited Promises SonarQube flagged, and lint wwwroot locally - #144

Merged
HandyS11 merged 2 commits into
developfrom
fix/sonar-unhandled-promises
Nov 1, 2026
Merged

HandyS11 merged 2 commits into
developfrom
fix/sonar-unhandled-promises

Conversation

@HandyS11

@HandyS11 HandyS11 commented Nov 1, 2026

Copy link
Copy Markdown
Owner

Summary

SonarQube's only open issues on develop were two javascript:S9383 findings ("Promises should not be left unhandled") in apps/RustPlusApi.CredentialsWeb/wwwroot/app.js: the delegated paste handler's submitPaste() call and the delegated copy button's copyText() call. Both functions report their own failures beside the control that triggered them, so the calls are now marked void with a comment saying where the failure handling lives.

Nothing checked that file locally: the C# side fails the build through SonarAnalyzer.CSharp, but the browser script had no analyzer behind it and Sonar.yml only analyzes develop after the merge. This PR adds the local guard so the same class of smell fails before the push.

Changes

  • app.js: the two intentionally unawaited calls are marked void, each with a one-line justification.
  • Dev-only Node toolchain in the app directory (package.json, eslint.config.mjs, tsconfig.json): npm run lint mirrors SonarQube's JavaScript rules — typescript-eslint's type-aware no-floating-promises (S9383) and no-misused-promises configured as Sonar's S6544 is (checksVoidReturn off), plus eslint-plugin-sonarjs recommended and ESLint recommended. Run before the fix it reported exactly Sonar's two findings and nothing else.
  • CI: new lint-web job runs the lint on every push and PR.
  • Pre-push hook: also runs the lint when a push touches the script or its lint setup. Verified by dry-run: passes on this branch, rejects an injected floating promise.
  • Pre-push hook bug fix (second commit): ReSharper exits 3 ("No items were found to cleanup") when a push's only C#-family files are .csproj/.props/.targets, and the hook rejected that. Pre-existing on develop; exit 3 now passes.
  • Dependabot: weekly npm group for the toolchain.
  • csproj: the Web SDK was publishing the three JSON files into the app output and Docker image; they are removed from Content. TypeScriptCompileBlocked stops Visual Studio's TypeScript build acting on tsconfig.json. node_modules added to .dockerignore.
  • Docs: docs/development/testing.md, docs/development/formatting.md, CLAUDE.md, AGENTS.md.

Test plan

  • npm run lint in the app directory: clean after the fix, two S9383 findings before it
  • dotnet build RustPlusApi.sln and the web app's 211 unit tests pass
  • dotnet publish of the web app no longer contains package.json, package-lock.json, tsconfig.json
  • Pre-push hook dry-run passes on this branch and rejects an injected unhandled promise
  • lint-web CI job green on this PR
  • SonarQube shows 0 open issues after the merge to develop

🤖 Generated with Claude Code

HandyS11 and others added 2 commits November 1, 2026 11:28
SonarQube's only open issues on develop were two javascript:S9383 findings
("Promises should not be left unhandled") in
apps/RustPlusApi.CredentialsWeb/wwwroot/app.js: the delegated paste handler's
submitPaste() call and the delegated copy button's copyText() call. Both
functions report their own failures next to the control that triggered them,
so the calls are now marked `void` with a comment saying where the failure
handling lives.

Nothing checked that file locally: the C# side fails the build through
SonarAnalyzer.CSharp, but the browser script had no analyzer behind it and
Sonar.yml only analyzes develop after the merge. The app directory now carries
a dev-only Node toolchain (package.json, eslint.config.mjs, tsconfig.json for
type-aware linting of plain JavaScript) whose `npm run lint` mirrors the rules
SonarQube applies: typescript-eslint's no-floating-promises (S9383) and
no-misused-promises configured as Sonar's S6544 is, plus eslint-plugin-sonarjs
recommended and ESLint recommended. Run before the fix it reported exactly
Sonar's two findings and nothing else.

The lint runs in a new CI.yml `lint-web` job on every push and PR, and in the
pre-push hook whenever a push touches the script or its lint setup. Dependabot
keeps the toolchain current. The csproj removes the three JSON files from
Content (the Web SDK was publishing them) and blocks Visual Studio's
TypeScript build from acting on tsconfig.json; .dockerignore drops
node_modules from the image build context.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ReSharper's cleanupcode exits 3 with "No items were found to cleanup" when
every included file is a .csproj/.props/.targets, and the pre-push hook treated
any non-zero exit as a formatting failure, so a push touching only project
files (such as this branch's csproj change) was rejected with nothing to fix.
Exit 3 now passes the check; every other non-zero code still blocks the push.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 1, 2026 17:37
@HandyS11
HandyS11 merged commit 30b34e4 into develop Nov 1, 2026
9 checks passed
@HandyS11
HandyS11 deleted the fix/sonar-unhandled-promises branch November 1, 2026 17:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

An unresolved moderate issue remains in the Web project, where node_modules is not excluded from the SDK's recursive Content globs, causing local builds and publishes to pick up thousands of unintended files.

1 open issue
1 file not reviewed
  • apps/RustPlusApi.CredentialsWeb/package-lock.json: Generated file
What changed in this PR

This PR resolves the two outstanding SonarQube javascript:S9383 ("Promises should not be left unhandled") findings in the credentials web app's browser script, and, more substantially, closes the gap that let those smells reach develop undetected: the browser JavaScript previously had no analyzer behind it locally or in pre-merge CI. It fits into the repo's existing "fail fast locally and in CI" philosophy (ReSharper formatting hook, strict C# analyzers) by giving wwwroot/app.js an ESLint toolchain that mirrors SonarQube's JS rules.

Changes:

  • Mark the two intentionally unawaited calls (submitPaste(), copyText()) with void plus a justifying comment.
  • Add a dev-only Node lint toolchain (package.json, package-lock.json, eslint.config.mjs, tsconfig.json) mirroring Sonar's no-floating-promises/no-misused-promises, wired into a new CI lint-web job, the pre-push hook, and a weekly Dependabot npm group.
  • Secondary fixes: pre-push hook now treats ReSharper exit code 3 ("No items to cleanup") as a pass; csproj stops the Web SDK from publishing the toolchain JSON files; node_modules added to .dockerignore; docs updated.
File Description
apps/​RustPlusApi.CredentialsWeb/​wwwroot/​app.js Marks the two floating-promise calls with void and comments.
apps/​RustPlusApi.CredentialsWeb/​eslint.config.mjs New flat ESLint config mirroring SonarQube JS rules via typescript-eslint.
apps/​RustPlusApi.CredentialsWeb/​tsconfig.json Minimal TS program so ESLint can run type-aware rules over the JS.
apps/​RustPlusApi.CredentialsWeb/​package.json /​ package-lock.json Pinned dev-only lint toolchain.
apps/​RustPlusApi.CredentialsWeb/​RustPlusApi.CredentialsWeb.csproj Blocks TS build step; removes three toolchain JSON files from Content — but does not exclude node_modules from the SDK globs (see comment).
.github/​workflows/​CI.yml Adds a lint-web job running the lint on push/PR.
.githooks/​pre-push Runs the web lint when the script/lint-setup changes; treats ReSharper exit 3 as a pass.
.github/​dependabot.yml Adds a weekly grouped npm update for the toolchain.
.dockerignore Excludes node_modules from the Docker build context.
CLAUDE.md, AGENTS.md, docs/​development/​formatting.md, docs/​development/​testing.md Document the new lint workflow.

Review effort: Balanced

Comment on lines +23 to +25
<!-- The lint toolchain's files, not app content: the Web SDK globs every *.json beside the project
as Content and would otherwise publish them (and ship them in the Docker image). -->
<Content Remove="package.json;package-lock.json;tsconfig.json" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants