Skip to content

chore: add SonarCloud sync script + CI integration - #93

Merged
BillyOutlast merged 18 commits into
developfrom
fix/sonarcloud-issues
Jul 26, 2026
Merged

chore: add SonarCloud sync script + CI integration#93
BillyOutlast merged 18 commits into
developfrom
fix/sonarcloud-issues

Conversation

@BillyOutlast

@BillyOutlast BillyOutlast commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Summary

Adds automated SonarCloud → GitHub Issues sync via CI.

Changes

  • **** — Bash script that queries SonarCloud API for unresolved BLOCKER/CRITICAL/MAJOR issues, groups them by (severity, rule), and creates/closes GitHub Issues
  • **** — Added sync step after SonarCloud scan (develop pushes only) with permission

How It Works

  1. SonarCloud scan runs on push to
  2. Sync script queries for unresolved issues
  3. Groups findings by (severity, rule) — one GitHub Issue per group
  4. Creates new issues for groups not yet tracked
  5. Closes GitHub Issues when all constituent SonarCloud findings are resolved

Modes

  • Default: Process only NEW findings (delta since last run)
  • ****: Process ALL unresolved findings
  • ****: Preview changes without making them

Issue Format

Matches existing pattern:

  • Title:
  • Labels: + or
  • Body: YAML frontmatter with SonarCloud keys + file table

Testing

  • Script syntax validated with
  • CI workflow passes actionlint
  • Sync step correctly skips on PRs (only runs on push to develop)
  • Dry-run mode available for testing

Next Steps

  1. Merge to
  2. Monitor CI logs for sync script output
  3. Run manually if needed to create issues for existing findings

Closes #N (will be auto-created for new findings)

Summary by CodeRabbit

  • New Features
    • Synchronize unresolved SonarCloud findings into GitHub Issues, consolidating higher-severity items for clearer tracking.
    • Added workflow support to preview changes (dry-run) and optionally update existing issue details (backfill).
  • Chores
    • Refined CI/SonarCloud execution and permissions, and added a post-success issue sync step after successful scans.
    • Improved security scanning outputs (CodeQL workflow simplification; OSV-Scanner now produces SARIF).
    • Simplified automated review configuration.
  • Documentation
    • Updated pre-commit guidance and the SonarCloud query example.
  • Accessibility & Localization
    • Localized the age-rating aria-label in the game editor UI.

John Smith added 11 commits July 26, 2026 12:08
- Fix #56: Create CHANGELOG.md and PR/issue templates
- Fix #57: Update CodeQL to autobuild for JS/TS and Rust
- Fix #58: Remove unwrap panic in torrential download.rs
- Fix #59: Document console.error in client-side error handler
- Fix #46: Remove @ts-expect-error by aligning authMecs type
- Fix #47: Add content-collections typegen script for sites/promo
- Fix #49: Update starlight-links-validator to Astro 7 compatible
- Fix #50: Add prettier-plugin-astro to sites/docs
- Fix #55: Replace OSV-Scanner reusable workflow with CLI
- Fix #62: Complete jsonwebtoken → jose migration
- Fix #63: Pin all Tauri sub-crate wildcard dependencies

Closes #46, #47, #49, #50, #55, #56, #57, #58, #59, #62, #63
- Issue 1: Update @astrojs/starlight to ^0.41.0 for peer dep compatibility
- Issue 2: Restore OSV-Scanner reusable workflow for diff-based PR gating
- Issue 3: Add proper error handling and logging for JWT verification
- Add redaction warning to bug template logs textarea
- Pin actions/checkout and osv-scanner-cli to commit SHAs
- Change JWT_TIME_WIGGLE to seconds (jose expects seconds)
- Use importX509 for X.509 certificates instead of importSPKI
- Wrap typegen:sanity cleanup to always run rm
- Use Set instead of Array for blacklistedFunctions in no-prisma-delete rule
- Replace Object.prototype.hasOwnProperty.call with Object.hasOwn
- Fix Vue :key bindings in v-for directives (Header, LibrarySearch, etc.)
- Replace role=status with <output> element for accessibility
- Associate form labels with controls in Metadata editor
- Extract nested ternaries into readable conditionals
- Extract nested template literals into variables
- Use project slug instead of array index as React key
- Pin GitHub Actions reusable workflow to full SHA hash
- Move security-events permission to job level in osv-scanner
- codeql.yml: use build-mode none for JS/TS and Rust
- osv-scanner.yml: add actions: read permission, SARIF upload for scan-scheduled
- AGENTS.md: add text language tag to code fence
- Metadata.vue: add aria-label for age rating value select
- news.tsx: stricter page param validation (digits-only, >= 1)
- event-handler.ts: restrict JWT algorithms to ES384

Refs: #92 (pre-existing LSP errors in news.tsx)
?page= now returns 404 instead of rendering page 1.
Check for null explicitly rather than falsy.
- osv-scanner.yml: keep SARIF upload + permissions from our branch
- event-handler.ts: keep algorithms: ['ES384'] from our branch
- codeql.yml: autobuild→none reverted by merge, re-applied
- Metadata.vue: use plain aria-label string instead of missing i18n key
- Create scripts/sonarcloud-sync.sh for SonarCloud → GitHub Issues sync
- Groups findings by (severity, rule) matching existing issue pattern
- Idempotent: creates/closes issues based on SonarCloud API state
- Supports --dry-run and --backfill modes
- Add sync step to ci.yml after SonarCloud scan (develop pushes only)
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds SonarCloud finding synchronization to GitHub Issues, updates CI and repository guidance, and localizes the game editor’s age-rating accessibility label.

Changes

SonarCloud issue synchronization

Layer / File(s) Summary
Finding synchronization
scripts/sonarcloud-sync.sh
Validates configuration, queries and groups unresolved findings, creates or updates labeled issues, closes resolved issues, and supports backfill and dry-run modes.
CI integration
.github/workflows/ci.yml
Adds permissions, scopes scan error handling to the scan step, and runs synchronization after successful pushes to develop.

Workflow and repository guidance

Layer / File(s) Summary
Workflow and guidance updates
.coderabbit.yaml, .github/workflows/codeql.yml, .github/workflows/osv-scanner.yml, AGENTS.md
Removes automatic review settings and CodeQL manual build steps, enables SARIF OSV-Scanner output, and updates Fallow and SonarCloud instructions.

Age-rating accessibility localization

Layer / File(s) Summary
Localized accessibility label
server/components/GameEditor/Metadata.vue, server/i18n/locales/en_us.json
Uses a translation key for the age-rating select’s aria-label and adds the English translation.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant SonarSync
  participant SonarCloud
  participant GitHubIssues
  GitHubActions->>SonarSync: Run on develop push with tokens
  SonarSync->>SonarCloud: Query unresolved findings
  SonarSync->>GitHubIssues: Create, update, or close labeled issues
Loading

Possibly related PRs

Suggested reviewers: invalid-email-address

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding a SonarCloud sync script and CI integration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sonarcloud-issues

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

@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@greptile-apps

greptile-apps Bot commented Jul 26, 2026

Copy link
Copy Markdown

Greptile Summary

This PR introduces a Bash script (scripts/sonarcloud-sync.sh) that queries SonarCloud for unresolved BLOCKER/CRITICAL/MAJOR findings, groups them by severity and rule, and creates or closes GitHub Issues accordingly. A new CI step runs this script on every push to develop after the SonarCloud scan completes.

  • scripts/sonarcloud-sync.sh: New sync script implementing delta/backfill/dry-run modes; groups findings into per-rule issues (≥3 findings) and catch-all issues (<3), and closes GitHub Issues when all constituent SonarCloud keys are resolved.
  • .github/workflows/ci.yml: Adds a Sync findings to GitHub Issues step to the existing sonar job, gated to push events on develop.
  • .coderabbit.yaml: Removes the auto_review block (WIP/DRAFT filtering).

Confidence Score: 3/5

The sync script has several bugs that prevent it from working correctly end-to-end; the CI job missing checkout permission also breaks the sonar job entirely.

The job-level permissions block in ci.yml silently drops contents:read, breaking actions/checkout. All four field-parsing loops use IFS=| against @TSV output so every variable after the first is always empty. Counter increments from zero exit under set -euo pipefail. The SonarCloud response is capped at 500 with no pagination. The newly flagged unanchored grep prevents resolved issues from being closed when keys share a prefix with an active finding.

Files Needing Attention: scripts/sonarcloud-sync.sh and .github/workflows/ci.yml both need attention before merge

Important Files Changed

Filename Overview
scripts/sonarcloud-sync.sh New sync script with several logic bugs: IFS/tsv mismatch breaks all field parsing, arithmetic increment exits under set -euo pipefail, no API pagination, and unanchored grep prevents resolved issues from being closed
.github/workflows/ci.yml Job-level permissions block replaces the workflow-level block, silently dropping contents:read, which breaks the actions/checkout step in the sonar job
.coderabbit.yaml Removes the auto_review block (draft/WIP filtering) from CodeRabbit config; straightforward cleanup with no functional issues

Sequence Diagram

sequenceDiagram
    participant CI as GitHub Actions (sonar job)
    participant SC as SonarCloud API
    participant GH as GitHub Issues API

    CI->>SC: GET /api/issues/search
    SC-->>CI: JSON response up to 500 issues
    CI->>CI: Group by severity and rule
    CI->>GH: gh issue list --label sonarcloud
    GH-->>CI: Existing open issues

    loop Each large group
        alt Exists
            CI->>CI: Skip or update
        else New
            CI->>GH: gh issue create
        end
    end

    loop Each catch-all bucket
        alt Exists
            CI->>CI: Skip or update
        else New
            CI->>GH: gh issue create
        end
    end

    loop Each existing sonarcloud issue
        CI->>CI: Check keys against unresolved list
        alt All resolved
            CI->>GH: gh issue close
        end
    end
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
scripts/sonarcloud-sync.sh:412-413
**Unanchored substring grep will falsely block issue closure**

`ALL_UNRESOLVED_KEYS` is a pipe-delimited string (e.g. `"AX1|AX10|AX11"`). Searching it with `grep -q "${key}"` treats `key` as a regex and does a substring match, so resolved key `"AX1"` will match unresolved keys `"AX10"` or `"AX11"`, causing the GitHub issue to never be closed. Wrap the key in pipe delimiters and use fixed-string matching to enforce exact key boundaries.

```suggestion
        # Check if this key still appears in unresolved results
        if echo "|${ALL_UNRESOLVED_KEYS}|" | grep -qF "|${key}|"; then
```

Reviews (3): Last reviewed commit: "chore: remove invalid auto_review key fr..." | Re-trigger Greptile

Comment on lines +153 to +162
GROUP_RULE["$gid"]="$full_rule"

msg=$(echo "$ISSUES_JSON" | jq -r '.[0].message // ""')
GROUP_MESSAGE["$gid"]="$msg"

log " Group ${gid}: ${count} issues"
done

# --- Step 3: Separate large and small groups ----------------------------------

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 IFS="|" used with jq @tsv output — all field parsing silently broken

@tsv produces tab-separated fields, not pipe-separated. With IFS="|" there is no delimiter match, so the entire line (tabs included) lands in the first variable and every subsequent variable is empty. This means $severity and $message are always "", making every gid the same degenerate key, so grouping and deduplication both fail completely.

The same mismatch occurs in four separate while IFS="|" read ... loops: the initial grouping pass here, the TITLE_TO_NUMBER build (~line 247), and both body-building functions. Change IFS="|" to IFS=$'\t' in all four loops.

Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/sonarcloud-sync.sh
Line: 153-162

Comment:
**`IFS="|"` used with `jq @tsv` output — all field parsing silently broken**

`@tsv` produces tab-separated fields, not pipe-separated. With `IFS="|"` there is no delimiter match, so the entire line (tabs included) lands in the first variable and every subsequent variable is empty. This means `$severity` and `$message` are always `""`, making every `gid` the same degenerate key, so grouping and deduplication both fail completely.

The same mismatch occurs in four separate `while IFS="|" read ...` loops: the initial grouping pass here, the `TITLE_TO_NUMBER` build (~line 247), and both body-building functions. Change `IFS="|"` to `IFS=$'\t'` in all four loops.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +223 to +225
CREATED=0
CLOSED=0
SKIPPED=0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 ((CREATED++)) when CREATED=0 evaluates arithmetically to 0, which makes bash return exit code 1. With set -euo pipefail active, the script terminates the very first time it tries to count a created (or closed, or skipped) issue from an initial count of 0. Use pre-increment (( ++CREATED )) or CREATED=$(( CREATED + 1 )) instead.

Suggested change
CREATED=0
CLOSED=0
SKIPPED=0
CREATED=0
CLOSED=0
SKIPPED=0
# NOTE: use (( ++VAR )) or VAR=$(( VAR + 1 )) — (( VAR++ )) when VAR=0 exits 1 under set -e
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/sonarcloud-sync.sh
Line: 223-225

Comment:
`((CREATED++))` when `CREATED=0` evaluates arithmetically to `0`, which makes bash return exit code 1. With `set -euo pipefail` active, the script terminates the very first time it tries to count a created (or closed, or skipped) issue from an initial count of 0. Use pre-increment `(( ++CREATED ))` or `CREATED=$(( CREATED + 1 ))` instead.

```suggestion
CREATED=0
CLOSED=0
SKIPPED=0
# NOTE: use (( ++VAR )) or VAR=$(( VAR + 1 )) — (( VAR++ )) when VAR=0 exits 1 under set -e
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread .github/workflows/ci.yml Outdated
Comment on lines +177 to +178
permissions:
issues: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Job-level permissions completely replaces the workflow-level block for that job — it does not merge. Adding only issues: write here drops the contents: read that the workflow-level block grants, so actions/checkout inside this job would fail with a 403 error. Add contents: read alongside issues: write.

Suggested change
permissions:
issues: write
permissions:
contents: read
issues: write
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/ci.yml
Line: 177-178

Comment:
Job-level `permissions` completely replaces the workflow-level block for that job — it does **not** merge. Adding only `issues: write` here drops the `contents: read` that the workflow-level block grants, so `actions/checkout` inside this job would fail with a 403 error. Add `contents: read` alongside `issues: write`.

```suggestion
    permissions:
      contents: read
      issues: write
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread scripts/sonarcloud-sync.sh Outdated
Comment on lines +97 to +104

# --- Step 1: Fetch unresolved issues from SonarCloud --------------------------

log "Fetching unresolved issues from SonarCloud (project: ${SONAR_PROJECT_KEY})..."

SONAR_RESPONSE=$(curl -sS -f \
-H "Authorization: Bearer ${SONAR_TOKEN}" \
"${SONAR_API}?componentKeys=${SONAR_PROJECT_KEY}&resolved=false&severities=${SEVERITIES}&ps=${PAGE_SIZE}") || {

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 SonarCloud API pagination not handled — findings beyond 500 silently dropped

SonarCloud's issues/search endpoint returns a paging object. When total > PAGE_SIZE (500), only the first page is fetched and remaining findings are never processed. The script logs TOTAL but never paginates.

Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/sonarcloud-sync.sh
Line: 97-104

Comment:
**SonarCloud API pagination not handled — findings beyond 500 silently dropped**

SonarCloud's `issues/search` endpoint returns a `paging` object. When `total > PAGE_SIZE` (500), only the first page is fetched and remaining findings are never processed. The script logs `TOTAL` but never paginates.

How can I resolve this? If you propose a fix, please make it concise.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 12

Caution

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

⚠️ Outside diff range comments (1)
.github/workflows/osv-scanner.yml (1)

30-42: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Keep the SARIF upload step running on findings.
osv-scanner exits non-zero when it finds vulnerabilities, so Upload SARIF never runs and scheduled scans won’t publish the report. Add continue-on-error: true on the scan step or if: always() on the upload step, and set SARIF explicitly with --format=sarif instead of relying on the .sarif filename.

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

In @.github/workflows/osv-scanner.yml around lines 30 - 42, Update the “Run
OSV-Scanner” step to explicitly request SARIF output with --format=sarif and
allow the step to continue when vulnerabilities are found; ensure the subsequent
“Upload SARIF” step still executes and uploads osv-scanner-results.sarif.
🧹 Nitpick comments (4)
.github/workflows/ci.yml (1)

193-198: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Sync failures will be invisible.

The job carries continue-on-error: true, so a failing sync step (bad token, API outage) is silently swallowed. Consider narrowing continue-on-error to the Sonar scan step only, so the sync step's failures actually surface.

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

In @.github/workflows/ci.yml around lines 193 - 198, Restrict continue-on-error
to the Sonar scan step rather than the entire job containing “Sync findings to
GitHub Issues.” Remove the broader job-level setting and ensure the sync step
running scripts/sonarcloud-sync.sh can fail the workflow when authentication or
API requests fail.
scripts/sonarcloud-sync.sh (2)

167-174: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

severity assigned but never used in this loop.

Only count is needed here; drop the assignment (matches the SonarCloud unused-variable hints at Lines 229 and 258 too).

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

In `@scripts/sonarcloud-sync.sh` around lines 167 - 174, Remove the unused
severity assignment from the loop over GROUP_KEYS in the large-group detection
block, leaving count and the LARGE_GROUPS threshold logic unchanged. Apply the
same cleanup to the corresponding unused severity assignments near the other
referenced loop locations.

Source: Linters/SAST tools


203-211: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

2>/dev/null || echo "[]" hides gh failures.

An auth/rate-limit error is indistinguishable from "no existing issues", which causes duplicate issue creation on the next run. Fail loudly instead of defaulting to an empty list.

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

In `@scripts/sonarcloud-sync.sh` around lines 203 - 211, Update the GH_ISSUES
retrieval in the sync flow to stop masking gh issue-list failures with an empty
JSON fallback. Preserve the successful JSON output and allow authentication,
rate-limit, or other gh errors to propagate so subsequent issue creation does
not proceed with missing existing-issue data.
.github/workflows/codeql.yml (1)

96-115: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

These steps are now unreachable.

All four steps require matrix.build-mode == 'manual', but javascript-typescript is set to none (Line 51), so the Node/pnpm/build steps never run. Either drop them or switch the JS matrix entry to manual if a build is actually needed for analysis quality.

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

In @.github/workflows/codeql.yml around lines 96 - 115, Resolve the unreachable
JavaScript/TypeScript setup and build steps in the CodeQL workflow: either
remove the Node.js, pnpm, dependency installation, and build steps, or change
the `javascript-typescript` matrix entry from `none` to `manual` so their
existing conditions can execute when the build is required for analysis.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 177-178: Update the job-level permissions block containing issues:
write to also grant contents: read, preserving the existing issues permission so
actions/checkout and the Sonar scan can read repository contents.

In `@AGENTS.md`:
- Around line 113-127: Update the “commit or open a PR” row in the task-map
table to instruct agents to run the enforced gate command `fallow audit --format
json --quiet --explain --gate-marker agent` before committing or pushing,
replacing the current `fallow audit --base <ref>` guidance.
- Around line 184-188: Update the SonarCloud MCP example near “SonarCloud
project key” to query the same unresolved scope as the sync script, including
unresolved findings across BLOCKER, CRITICAL, and MAJOR severities;
alternatively, explicitly label the current issueStatuses=["OPEN"] example as
open-only.

In `@scripts/sonarcloud-sync.sh`:
- Around line 427-431: Update the issue-closing flow around gh issue close so
the success log and CLOSED increment occur only when the close command succeeds;
keep the existing warn path for failures without reporting them as closed.
- Around line 238-254: Update the body rendering in the SonarCloud finding
construction to avoid echo -e interpreting backslash sequences from message and
other interpolated content. Preserve the literal newline structure while
emitting the assembled body with printf or equivalent, ensuring ${message} is
interpolated verbatim and the existing table and fix sections remain unchanged.
- Around line 102-115: Update the SonarCloud request flow around SONAR_RESPONSE
to paginate through all unresolved findings using the API’s total/page metadata,
requesting pages from p=1 through the required final page and accumulating every
issue before group computation and Step 6. Preserve the existing filters and
PAGE_SIZE, and ensure downstream logic uses the complete collection rather than
only the first response.
- Around line 49-52: Update the SONAR_TOKEN check in scripts/sonarcloud-sync.sh
to safely handle an unset variable under set -u, matching the existing GH_TOKEN
defaulting pattern or using an equivalent unset-safe validation. Preserve the
intended FATAL message and exit behavior when SONAR_TOKEN is missing or empty.
- Around line 124-129: Update every affected read loop in
scripts/sonarcloud-sync.sh, including the loops near the GROUP_KEYS population
and the referenced later sections, to use tab-delimited parsing consistent with
jq’s `@tsv` output instead of IFS="|". Preserve the existing rule, severity, and
message assignments so group_id and subsequent grouping receive the correct
fields.
- Line 338: Replace the post-increment arithmetic commands for CREATED and the
counters at the referenced locations with an increment form that does not return
the pre-increment zero value, preserving each counter’s existing update behavior
under set -e.
- Around line 409-417: Update the unresolved-key check in the key-processing
loop to perform exact JSON-based key matching instead of regex substring
matching against the joined ALL_UNRESOLVED_KEYS string. Ensure keys that are
only prefixes or substrings of other keys do not keep all_resolved false, while
preserving the existing skip-empty and early-break behavior.
- Around line 403-404: Update the regex in the issue-body parsing block around
issue_body and BASH_REMATCH to match the explicit allowed sonarcloud key-list
character set instead of using [^\n]. Preserve extraction of the complete keys
value, including keys containing the letter “n”, so key_array receives all
listed keys.

In `@server/components/GameEditor/Metadata.vue`:
- Around line 107-110: Replace the hard-coded aria-label on the ageRatingValue
control with a hard-coded i18n key bound through $t(...), and add the
corresponding localized translation entry using the existing server Vue
translation conventions.

---

Outside diff comments:
In @.github/workflows/osv-scanner.yml:
- Around line 30-42: Update the “Run OSV-Scanner” step to explicitly request
SARIF output with --format=sarif and allow the step to continue when
vulnerabilities are found; ensure the subsequent “Upload SARIF” step still
executes and uploads osv-scanner-results.sarif.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 193-198: Restrict continue-on-error to the Sonar scan step rather
than the entire job containing “Sync findings to GitHub Issues.” Remove the
broader job-level setting and ensure the sync step running
scripts/sonarcloud-sync.sh can fail the workflow when authentication or API
requests fail.

In @.github/workflows/codeql.yml:
- Around line 96-115: Resolve the unreachable JavaScript/TypeScript setup and
build steps in the CodeQL workflow: either remove the Node.js, pnpm, dependency
installation, and build steps, or change the `javascript-typescript` matrix
entry from `none` to `manual` so their existing conditions can execute when the
build is required for analysis.

In `@scripts/sonarcloud-sync.sh`:
- Around line 167-174: Remove the unused severity assignment from the loop over
GROUP_KEYS in the large-group detection block, leaving count and the
LARGE_GROUPS threshold logic unchanged. Apply the same cleanup to the
corresponding unused severity assignments near the other referenced loop
locations.
- Around line 203-211: Update the GH_ISSUES retrieval in the sync flow to stop
masking gh issue-list failures with an empty JSON fallback. Preserve the
successful JSON output and allow authentication, rate-limit, or other gh errors
to propagate so subsequent issue creation does not proceed with missing
existing-issue data.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 299e663e-1876-4e90-ab6b-6957ca6c9b9a

📥 Commits

Reviewing files that changed from the base of the PR and between 31fe290 and d2e7474.

📒 Files selected for processing (23)
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/osv-scanner.yml
  • AGENTS.md
  • desktop/main/components/Header.vue
  • desktop/main/components/HeaderUserWidget.vue
  • desktop/main/components/LibrarySearch.vue
  • desktop/main/pages/auth/code.vue
  • desktop/main/pages/library/[id]/index.vue
  • desktop/main/pages/queue.vue
  • libraries/base/components/LoadingButton.vue
  • scripts/sonarcloud-sync.sh
  • server/components/CodeInput.vue
  • server/components/GameEditor/Metadata.vue
  • server/components/GameEditor/VersionConfig.vue
  • server/components/Selector/MultiItem.vue
  • server/pages/admin/library/index.vue
  • server/rules/no-prisma-delete.ts
  • server/server/internal/clients/event-handler.ts
  • server/server/internal/metadata/giantbomb.ts
  • server/server/internal/metadata/steam.ts
  • sites/promo/src/components/comparison.tsx
  • sites/promo/src/components/news.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 12

Caution

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

⚠️ Outside diff range comments (1)
.github/workflows/osv-scanner.yml (1)

30-42: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Keep the SARIF upload step running on findings.
osv-scanner exits non-zero when it finds vulnerabilities, so Upload SARIF never runs and scheduled scans won’t publish the report. Add continue-on-error: true on the scan step or if: always() on the upload step, and set SARIF explicitly with --format=sarif instead of relying on the .sarif filename.

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

In @.github/workflows/osv-scanner.yml around lines 30 - 42, Update the “Run
OSV-Scanner” step to explicitly request SARIF output with --format=sarif and
allow the step to continue when vulnerabilities are found; ensure the subsequent
“Upload SARIF” step still executes and uploads osv-scanner-results.sarif.
🧹 Nitpick comments (4)
.github/workflows/ci.yml (1)

193-198: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Sync failures will be invisible.

The job carries continue-on-error: true, so a failing sync step (bad token, API outage) is silently swallowed. Consider narrowing continue-on-error to the Sonar scan step only, so the sync step's failures actually surface.

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

In @.github/workflows/ci.yml around lines 193 - 198, Restrict continue-on-error
to the Sonar scan step rather than the entire job containing “Sync findings to
GitHub Issues.” Remove the broader job-level setting and ensure the sync step
running scripts/sonarcloud-sync.sh can fail the workflow when authentication or
API requests fail.
scripts/sonarcloud-sync.sh (2)

167-174: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

severity assigned but never used in this loop.

Only count is needed here; drop the assignment (matches the SonarCloud unused-variable hints at Lines 229 and 258 too).

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

In `@scripts/sonarcloud-sync.sh` around lines 167 - 174, Remove the unused
severity assignment from the loop over GROUP_KEYS in the large-group detection
block, leaving count and the LARGE_GROUPS threshold logic unchanged. Apply the
same cleanup to the corresponding unused severity assignments near the other
referenced loop locations.

Source: Linters/SAST tools


203-211: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

2>/dev/null || echo "[]" hides gh failures.

An auth/rate-limit error is indistinguishable from "no existing issues", which causes duplicate issue creation on the next run. Fail loudly instead of defaulting to an empty list.

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

In `@scripts/sonarcloud-sync.sh` around lines 203 - 211, Update the GH_ISSUES
retrieval in the sync flow to stop masking gh issue-list failures with an empty
JSON fallback. Preserve the successful JSON output and allow authentication,
rate-limit, or other gh errors to propagate so subsequent issue creation does
not proceed with missing existing-issue data.
.github/workflows/codeql.yml (1)

96-115: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

These steps are now unreachable.

All four steps require matrix.build-mode == 'manual', but javascript-typescript is set to none (Line 51), so the Node/pnpm/build steps never run. Either drop them or switch the JS matrix entry to manual if a build is actually needed for analysis quality.

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

In @.github/workflows/codeql.yml around lines 96 - 115, Resolve the unreachable
JavaScript/TypeScript setup and build steps in the CodeQL workflow: either
remove the Node.js, pnpm, dependency installation, and build steps, or change
the `javascript-typescript` matrix entry from `none` to `manual` so their
existing conditions can execute when the build is required for analysis.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 177-178: Update the job-level permissions block containing issues:
write to also grant contents: read, preserving the existing issues permission so
actions/checkout and the Sonar scan can read repository contents.

In `@AGENTS.md`:
- Around line 113-127: Update the “commit or open a PR” row in the task-map
table to instruct agents to run the enforced gate command `fallow audit --format
json --quiet --explain --gate-marker agent` before committing or pushing,
replacing the current `fallow audit --base <ref>` guidance.
- Around line 184-188: Update the SonarCloud MCP example near “SonarCloud
project key” to query the same unresolved scope as the sync script, including
unresolved findings across BLOCKER, CRITICAL, and MAJOR severities;
alternatively, explicitly label the current issueStatuses=["OPEN"] example as
open-only.

In `@scripts/sonarcloud-sync.sh`:
- Around line 427-431: Update the issue-closing flow around gh issue close so
the success log and CLOSED increment occur only when the close command succeeds;
keep the existing warn path for failures without reporting them as closed.
- Around line 238-254: Update the body rendering in the SonarCloud finding
construction to avoid echo -e interpreting backslash sequences from message and
other interpolated content. Preserve the literal newline structure while
emitting the assembled body with printf or equivalent, ensuring ${message} is
interpolated verbatim and the existing table and fix sections remain unchanged.
- Around line 102-115: Update the SonarCloud request flow around SONAR_RESPONSE
to paginate through all unresolved findings using the API’s total/page metadata,
requesting pages from p=1 through the required final page and accumulating every
issue before group computation and Step 6. Preserve the existing filters and
PAGE_SIZE, and ensure downstream logic uses the complete collection rather than
only the first response.
- Around line 49-52: Update the SONAR_TOKEN check in scripts/sonarcloud-sync.sh
to safely handle an unset variable under set -u, matching the existing GH_TOKEN
defaulting pattern or using an equivalent unset-safe validation. Preserve the
intended FATAL message and exit behavior when SONAR_TOKEN is missing or empty.
- Around line 124-129: Update every affected read loop in
scripts/sonarcloud-sync.sh, including the loops near the GROUP_KEYS population
and the referenced later sections, to use tab-delimited parsing consistent with
jq’s `@tsv` output instead of IFS="|". Preserve the existing rule, severity, and
message assignments so group_id and subsequent grouping receive the correct
fields.
- Line 338: Replace the post-increment arithmetic commands for CREATED and the
counters at the referenced locations with an increment form that does not return
the pre-increment zero value, preserving each counter’s existing update behavior
under set -e.
- Around line 409-417: Update the unresolved-key check in the key-processing
loop to perform exact JSON-based key matching instead of regex substring
matching against the joined ALL_UNRESOLVED_KEYS string. Ensure keys that are
only prefixes or substrings of other keys do not keep all_resolved false, while
preserving the existing skip-empty and early-break behavior.
- Around line 403-404: Update the regex in the issue-body parsing block around
issue_body and BASH_REMATCH to match the explicit allowed sonarcloud key-list
character set instead of using [^\n]. Preserve extraction of the complete keys
value, including keys containing the letter “n”, so key_array receives all
listed keys.

In `@server/components/GameEditor/Metadata.vue`:
- Around line 107-110: Replace the hard-coded aria-label on the ageRatingValue
control with a hard-coded i18n key bound through $t(...), and add the
corresponding localized translation entry using the existing server Vue
translation conventions.

---

Outside diff comments:
In @.github/workflows/osv-scanner.yml:
- Around line 30-42: Update the “Run OSV-Scanner” step to explicitly request
SARIF output with --format=sarif and allow the step to continue when
vulnerabilities are found; ensure the subsequent “Upload SARIF” step still
executes and uploads osv-scanner-results.sarif.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 193-198: Restrict continue-on-error to the Sonar scan step rather
than the entire job containing “Sync findings to GitHub Issues.” Remove the
broader job-level setting and ensure the sync step running
scripts/sonarcloud-sync.sh can fail the workflow when authentication or API
requests fail.

In @.github/workflows/codeql.yml:
- Around line 96-115: Resolve the unreachable JavaScript/TypeScript setup and
build steps in the CodeQL workflow: either remove the Node.js, pnpm, dependency
installation, and build steps, or change the `javascript-typescript` matrix
entry from `none` to `manual` so their existing conditions can execute when the
build is required for analysis.

In `@scripts/sonarcloud-sync.sh`:
- Around line 167-174: Remove the unused severity assignment from the loop over
GROUP_KEYS in the large-group detection block, leaving count and the
LARGE_GROUPS threshold logic unchanged. Apply the same cleanup to the
corresponding unused severity assignments near the other referenced loop
locations.
- Around line 203-211: Update the GH_ISSUES retrieval in the sync flow to stop
masking gh issue-list failures with an empty JSON fallback. Preserve the
successful JSON output and allow authentication, rate-limit, or other gh errors
to propagate so subsequent issue creation does not proceed with missing
existing-issue data.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 299e663e-1876-4e90-ab6b-6957ca6c9b9a

📥 Commits

Reviewing files that changed from the base of the PR and between 31fe290 and d2e7474.

📒 Files selected for processing (23)
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/osv-scanner.yml
  • AGENTS.md
  • desktop/main/components/Header.vue
  • desktop/main/components/HeaderUserWidget.vue
  • desktop/main/components/LibrarySearch.vue
  • desktop/main/pages/auth/code.vue
  • desktop/main/pages/library/[id]/index.vue
  • desktop/main/pages/queue.vue
  • libraries/base/components/LoadingButton.vue
  • scripts/sonarcloud-sync.sh
  • server/components/CodeInput.vue
  • server/components/GameEditor/Metadata.vue
  • server/components/GameEditor/VersionConfig.vue
  • server/components/Selector/MultiItem.vue
  • server/pages/admin/library/index.vue
  • server/rules/no-prisma-delete.ts
  • server/server/internal/clients/event-handler.ts
  • server/server/internal/metadata/giantbomb.ts
  • server/server/internal/metadata/steam.ts
  • sites/promo/src/components/comparison.tsx
  • sites/promo/src/components/news.tsx
🛑 Comments failed to post (12)
.github/workflows/ci.yml (1)

177-178: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Add contents: read to the job-level permissions block.

Declaring permissions: at the job level resets every unlisted scope to none, so actions/checkout (line 180) and the Sonar scan lose read access to the repository contents.

🛠️ Proposed fix
     permissions:
+      contents: read
       issues: write
📝 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.

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

In @.github/workflows/ci.yml around lines 177 - 178, Update the job-level
permissions block containing issues: write to also grant contents: read,
preserving the existing issues permission so actions/checkout and the Sonar scan
can read repository contents.
AGENTS.md (2)

113-127: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Align the task-map commit command with the enforced Fallow gate.

The table currently instructs agents to run fallow audit --base <ref> for commits or PRs, while the setup hook requires fallow audit --format json --quiet --explain --gate-marker agent before commits and pushes. This can cause agents to skip the actual blocking gate.

Suggested correction
-| commit or open a PR                                               | `fallow audit --base <ref>`                                                          |
+| commit or open a PR                                               | `fallow audit --format json --quiet --explain --gate-marker agent`                  |
+| compare a change against a base ref                               | `fallow audit --base <ref>`                                                          |

As per coding guidelines, before committing or pushing, run fallow audit --format json --quiet --explain --gate-marker agent.

📝 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.

| When the agent is about to...                                     | Run                                                                                  |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| delete an "unused" export or file                                 | `fallow dead-code --trace <file>:<export>`                                           |
| delete an "unused" dependency                                     | `fallow dead-code --trace-dependency <name>`                                         |
| commit or open a PR                                               | `fallow audit --format json --quiet --explain --gate-marker agent`                  |
| compare a change against a base ref                               | `fallow audit --base <ref>`                                                          |
| prioritize refactoring                                            | `fallow health --hotspots --targets`                                                 |
| ask who owns code                                                 | `fallow health --ownership`                                                          |
| check untested-but-reachable code                                 | `fallow health --coverage-gaps`                                                      |
| consolidate duplication                                           | `fallow dupes --trace dup:<fingerprint>`                                             |
| find feature flags                                                | `fallow flags`                                                                       |
| check which architecture rules apply to a file before changing it | `fallow guard <files>`                                                               |
| surface security candidates                                       | `fallow security`                                                                    |
| understand a finding                                              | `fallow explain <issue-type>`                                                        |
| scope a monorepo                                                  | `--workspace <glob> / --changed-workspaces <ref>` (global flags, prefix any command) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@AGENTS.md` around lines 113 - 127, Update the “commit or open a PR” row in
the task-map table to instruct agents to run the enforced gate command `fallow
audit --format json --quiet --explain --gate-marker agent` before committing or
pushing, replacing the current `fallow audit --base <ref>` guidance.

Source: Coding guidelines


184-188: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the relevant files and inspect the specific ranges.
git ls-files | rg '(^|/)(AGENTS\.md|scripts/sonarcloud-sync\.sh)$'

echo '--- AGENTS.md (around lines 184-188) ---'
if [ -f AGENTS.md ]; then
  sed -n '176,196p' AGENTS.md
fi

echo '--- scripts/sonarcloud-sync.sh ---'
if [ -f scripts/sonarcloud-sync.sh ]; then
  wc -l scripts/sonarcloud-sync.sh
  sed -n '1,240p' scripts/sonarcloud-sync.sh
fi

Repository: BillyOutlast/drop

Length of output: 8782


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find any SonarCloud-related docs or MCP examples for issue queries.
rg -n "search_sonar_issues_in_projects|issueStatuses|resolved=false|BLOCKER|CRITICAL|MAJOR|SonarCloud" AGENTS.md scripts .github README.md docs -g '!**/node_modules/**'

Repository: BillyOutlast/drop

Length of output: 4191


🌐 Web query:

SonarQube issue statuses OPEN CONFIRMED REOPENED RESOLVED CLOSED resolved=false severity BLOCKER CRITICAL MAJOR

💡 Result:

In modern SonarQube versions (including recent 10.x and 2026.x releases), the issue lifecycle and status terminology have evolved, moving away from some traditional statuses [1][2][3]. Current Issue Statuses The primary statuses used in the SonarQube interface are [1][3]: - Open: The initial status for new issues or issues that persist after analysis [1][3]. - Accepted: Set manually by an authorized user to indicate that the issue is acknowledged but will not be fixed currently [1][3]. - False positive: Set manually by an authorized user if the analysis is considered incorrect [1][3]. - Fixed: Set automatically by SonarQube after an analysis confirms the issue is no longer present in the code [1][3]. Note: Older statuses like Confirmed, Resolved, Reopened, and Closed have been deprecated or integrated into this simplified lifecycle [2]. For example, the former "Resolved" and "Closed" states are largely superseded by automatic "Fixed" status assignment and administrative status management [2]. API Filtering and Parameters When interacting with the SonarQube API (typically /api/issues/search), you can filter issues using the following parameters [4]: - resolved: A boolean parameter [4]. Setting resolved=false filters for active, non-fixed issues [5]. - severities: A comma-separated list of severity levels to filter by (e.g., BLOCKER,CRITICAL,MAJOR) [6][5]. Example API usage for your specific criteria: GET /api/issues/search?resolved=false&severities=BLOCKER,CRITICAL,MAJOR Important Consideration for Modern Instances If your SonarQube instance uses Multi-Quality Rule (MQR) mode, the traditional "Severity" field may be superseded or complemented by "Impacts" [7]. In such environments, use the impactSeverities filter instead of the legacy severities parameter to ensure accurate results [7]. Always verify the response structure, as MQR-enabled systems provide severity information within an impacts array rather than a single top-level severity field [7].

Citations:


Use the unresolved Sonar scope in the MCP example. issueStatuses=["OPEN"] is narrower than the sync script’s resolved=false + BLOCKER/CRITICAL/MAJOR query, so it can miss active findings. Either use the unresolved-status/severity equivalent or label it open-only.

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

In `@AGENTS.md` around lines 184 - 188, Update the SonarCloud MCP example near
“SonarCloud project key” to query the same unresolved scope as the sync script,
including unresolved findings across BLOCKER, CRITICAL, and MAJOR severities;
alternatively, explicitly label the current issueStatuses=["OPEN"] example as
open-only.
scripts/sonarcloud-sync.sh (8)

49-52: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

$SONAR_TOKEN is unbound under set -u.

set -euo pipefail is active and SONAR_TOKEN is never defaulted (unlike GH_TOKEN on Line 28). If the variable is unset, the script dies with SONAR_TOKEN: unbound variable instead of the intended FATAL message.

🐛 Proposed fix
-if [[ -z "$SONAR_TOKEN" ]]; then
+SONAR_TOKEN="${SONAR_TOKEN:-}"
+if [[ -z "$SONAR_TOKEN" ]]; then
📝 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.

SONAR_TOKEN="${SONAR_TOKEN:-}"
if [[ -z "$SONAR_TOKEN" ]]; then
  echo "FATAL: SONAR_TOKEN is not set" >&2
  exit 1
fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/sonarcloud-sync.sh` around lines 49 - 52, Update the SONAR_TOKEN
check in scripts/sonarcloud-sync.sh to safely handle an unset variable under set
-u, matching the existing GH_TOKEN defaulting pattern or using an equivalent
unset-safe validation. Preserve the intended FATAL message and exit behavior
when SONAR_TOKEN is missing or empty.

102-115: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

No pagination: findings beyond the first 500 are silently ignored.

ps=500 is SonarCloud's max page size; .total is logged but .paging is never followed. On a project with more than 500 unresolved BLOCKER/CRITICAL/MAJOR issues, groups are computed from a partial set and — worse — Step 6 will see keys "missing" from the truncated result and close still-valid issues. Loop over p=1..N until all issues are collected.

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

In `@scripts/sonarcloud-sync.sh` around lines 102 - 115, Update the SonarCloud
request flow around SONAR_RESPONSE to paginate through all unresolved findings
using the API’s total/page metadata, requesting pages from p=1 through the
required final page and accumulating every issue before group computation and
Step 6. Preserve the existing filters and PAGE_SIZE, and ensure downstream logic
uses the complete collection rather than only the first response.

124-129: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

IFS="|" does not match @tsv output.

jq -r ... | @tsv`` emits tab-separated fields, but the reader splits on |. Every field lands in `$rule` and `$severity`/`$message` are empty, so `group_id` produces `"/"` and grouping breaks entirely. Same mismatch at Lines 215-219, 245-251, and 271-279.

🐛 Proposed fix
-while IFS="|" read -r rule severity message; do
+while IFS=$'\t' read -r rule severity message; do
📝 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.

while IFS=$'\t' read -r rule severity message; do
  gid=$(group_id "$severity" "$rule")
  GROUP_KEYS["$gid"]=1
done < <(
  echo "$SONAR_RESPONSE" | jq -r '.issues[] | [.rule, .severity, .message] | `@tsv`'
)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/sonarcloud-sync.sh` around lines 124 - 129, Update every affected
read loop in scripts/sonarcloud-sync.sh, including the loops near the GROUP_KEYS
population and the referenced later sections, to use tab-delimited parsing
consistent with jq’s `@tsv` output instead of IFS="|". Preserve the existing rule,
severity, and message assignments so group_id and subsequent grouping receive
the correct fields.

238-254: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

echo -e expands escapes inside SonarCloud messages.

The body is assembled with literal \n markers and expanded via echo -e, so any backslash sequence present in ${message} (e.g. regex rule messages containing \t, \d) is also interpreted and the rendered issue body is corrupted. Prefer a heredoc / printf '%s\n' accumulation and interpolate messages verbatim.

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

In `@scripts/sonarcloud-sync.sh` around lines 238 - 254, Update the body rendering
in the SonarCloud finding construction to avoid echo -e interpreting backslash
sequences from message and other interpolated content. Preserve the literal
newline structure while emitting the assembled body with printf or equivalent,
ensuring ${message} is interpolated verbatim and the existing table and fix
sections remain unchanged.

338-338: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

((VAR++)) aborts the script under set -e.

Post-increment from 0 evaluates to 0, so the arithmetic command exits with status 1 and set -e terminates the run right after the first created issue. Same hazard at Lines 321, 367, 382, and 433.

🐛 Proposed fix
-    ((CREATED++))
+    CREATED=$((CREATED + 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.

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

In `@scripts/sonarcloud-sync.sh` at line 338, Replace the post-increment
arithmetic commands for CREATED and the counters at the referenced locations
with an increment form that does not return the pre-increment zero value,
preserving each counter’s existing update behavior under set -e.

403-404: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

[^\n] in a bash regex is not "not newline".

Bash ERE bracket expressions don't process \n; [^\n] means "not \ and not n". Key lists containing an n are truncated, so key_array is incomplete and issues can be closed while findings are still open. Match the key charset explicitly instead.

🐛 Proposed fix
-    if [[ "$issue_body" =~ sonarcloud-keys:\ ([^\n]+) ]]; then
+    if [[ "$issue_body" =~ sonarcloud-keys:[[:space:]]([-_A-Za-z0-9,[:space:]]+) ]]; then
📝 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.

    if [[ "$issue_body" =~ sonarcloud-keys:[[:space:]]([-_A-Za-z0-9,[:space:]]+) ]]; then
      keys="${BASH_REMATCH[1]}"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/sonarcloud-sync.sh` around lines 403 - 404, Update the regex in the
issue-body parsing block around issue_body and BASH_REMATCH to match the
explicit allowed sonarcloud key-list character set instead of using [^\n].
Preserve extraction of the complete keys value, including keys containing the
letter “n”, so key_array receives all listed keys.

409-417: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Unanchored grep on a joined key string gives false "still open" matches.

grep -q "${key}" treats the key as a regex and matches substrings of the |-joined blob, so a resolved key that is a prefix/substring of another key keeps the issue open forever. Use exact matching against the JSON directly.

♻️ Proposed fix
-        if echo "$ALL_UNRESOLVED_KEYS" | grep -q "${key}"; then
+        if printf '%s\n' "$ALL_UNRESOLVED_KEYS" | tr '|' '\n' | grep -qxF "$key"; then
📝 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.

      for key in "${key_array[@]}"; do
        key=$(echo "$key" | xargs)  # trim
        [[ -z "$key" ]] && continue
        # Check if this key still appears in unresolved results
        if printf '%s\n' "$ALL_UNRESOLVED_KEYS" | tr '|' '\n' | grep -qxF "$key"; then
          all_resolved=false
          break
        fi
      done
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/sonarcloud-sync.sh` around lines 409 - 417, Update the unresolved-key
check in the key-processing loop to perform exact JSON-based key matching
instead of regex substring matching against the joined ALL_UNRESOLVED_KEYS
string. Ensure keys that are only prefixes or substrings of other keys do not
keep all_resolved false, while preserving the existing skip-empty and
early-break behavior.

427-431: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

"Closed issue" is logged even when the close failed.

warn ... || log ... ordering means the success log runs unconditionally, and CLOSED is incremented regardless. Move the log inside the success branch.

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

In `@scripts/sonarcloud-sync.sh` around lines 427 - 431, Update the issue-closing
flow around gh issue close so the success log and CLOSED increment occur only
when the close command succeeds; keep the existing warn path for failures
without reporting them as closed.
server/components/GameEditor/Metadata.vue (1)

107-110: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Localize the new accessible name.

Line [110] introduces a hard-coded English string in a server Vue template, so this label will not change with the active locale. Add a translation key and bind it with $t(...).

As per coding guidelines: server Vue templates must use hard-coded i18n keys rather than untranslated user-facing strings.

Proposed fix
-                  aria-label="Age rating value"
+                  :aria-label="$t('library.admin.game.ageRatingValue')"
📝 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.

                  id="ageRatingValue"
                  v-model="newAgeRatingValue"
                  :disabled="!newAgeRatingOrg"
                  :aria-label="$t('library.admin.game.ageRatingValue')"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/components/GameEditor/Metadata.vue` around lines 107 - 110, Replace
the hard-coded aria-label on the ageRatingValue control with a hard-coded i18n
key bound through $t(...), and add the corresponding localized translation entry
using the existing server Vue translation conventions.

Source: Coding guidelines

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Note

Unit test generation is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

Comment thread scripts/sonarcloud-sync.sh Outdated
Comment on lines +412 to +413
# Check if this key still appears in unresolved results
if echo "$ALL_UNRESOLVED_KEYS" | grep -q "${key}"; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Unanchored substring grep will falsely block issue closure

ALL_UNRESOLVED_KEYS is a pipe-delimited string (e.g. "AX1|AX10|AX11"). Searching it with grep -q "${key}" treats key as a regex and does a substring match, so resolved key "AX1" will match unresolved keys "AX10" or "AX11", causing the GitHub issue to never be closed. Wrap the key in pipe delimiters and use fixed-string matching to enforce exact key boundaries.

Suggested change
# Check if this key still appears in unresolved results
if echo "$ALL_UNRESOLVED_KEYS" | grep -q "${key}"; then
# Check if this key still appears in unresolved results
if echo "|${ALL_UNRESOLVED_KEYS}|" | grep -qF "|${key}|"; then
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/sonarcloud-sync.sh
Line: 412-413

Comment:
**Unanchored substring grep will falsely block issue closure**

`ALL_UNRESOLVED_KEYS` is a pipe-delimited string (e.g. `"AX1|AX10|AX11"`). Searching it with `grep -q "${key}"` treats `key` as a regex and does a substring match, so resolved key `"AX1"` will match unresolved keys `"AX10"` or `"AX11"`, causing the GitHub issue to never be closed. Wrap the key in pipe delimiters and use fixed-string matching to enforce exact key boundaries.

```suggestion
        # Check if this key still appears in unresolved results
        if echo "|${ALL_UNRESOLVED_KEYS}|" | grep -qF "|${key}|"; then
```

How can I resolve this? If you propose a fix, please make it concise.

1. Fix IFS delimiter: @TSV produces tabs, not pipes
2. Fix arithmetic increment: ((VAR++)) fails under set -e when VAR=0
3. Fix CI permissions: add contents: read alongside issues: write
4. Add SonarCloud API pagination for >500 issues

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

BillyOutlast has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

✅ Created PR with unit tests: #94

- ci.yml: move continue-on-error to Sonar scan step only
- sonarcloud-sync.sh: fix close flow, printf, regex, key matching, set -u
- codeql.yml: change javascript-typescript build-mode to manual
- AGENTS.md: update fallow audit command and MCP example
- osv-scanner.yml: add --format=sarif
- Metadata.vue: replace hard-coded aria-label with i18n key

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

BillyOutlast has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

John Smith added 2 commits July 26, 2026 17:41
JavaScript/TypeScript doesn't support manual build mode in CodeQL.
Removed unreachable setup/build steps.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (2)
.github/workflows/ci.yml (2)

176-178: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Scope issues: write to the push-only synchronization job.

This permission is granted to the entire sonar job, including pull_request runs, although issue synchronization only runs on pushes to develop. Split the synchronizer into a push-only job with issues: write, while keeping the scan job read-only.

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

In @.github/workflows/ci.yml around lines 176 - 178, Update the workflow around
the sonar job to split issue synchronization into a separate push-only job that
has issues: write permission, while keeping the scan job read-only with
contents: read and retaining pull_request execution only for scanning.

190-199: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not synchronize findings after a failed Sonar scan.

continue-on-error: true allows the sync step to run even when analysis fails. The script can then create or close GitHub Issues from stale or incomplete SonarCloud results. Give the scan step an id and require steps.<id>.outcome == 'success' in the sync condition, or remove continue-on-error.

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

In @.github/workflows/ci.yml around lines 190 - 199, Prevent “Sync findings to
GitHub Issues” from running after a failed SonarQube scan by assigning an id to
the SonarSource/sonarqube-scan-action step and adding its successful outcome to
the sync step’s existing condition. Preserve the current push-to-develop
restriction and continue-on-error behavior unless removing it is necessary.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In @.github/workflows/ci.yml:
- Around line 176-178: Update the workflow around the sonar job to split issue
synchronization into a separate push-only job that has issues: write permission,
while keeping the scan job read-only with contents: read and retaining
pull_request execution only for scanning.
- Around line 190-199: Prevent “Sync findings to GitHub Issues” from running
after a failed SonarQube scan by assigning an id to the
SonarSource/sonarqube-scan-action step and adding its successful outcome to the
sync step’s existing condition. Preserve the current push-to-develop restriction
and continue-on-error behavior unless removing it is necessary.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2be4a0c6-1085-40c5-b578-69dbe7f4f624

📥 Commits

Reviewing files that changed from the base of the PR and between e0fe324 and 13e73c6.

📒 Files selected for processing (7)
  • .github/workflows/ci.yml
  • .github/workflows/codeql.yml
  • .github/workflows/osv-scanner.yml
  • AGENTS.md
  • scripts/sonarcloud-sync.sh
  • server/components/GameEditor/Metadata.vue
  • server/i18n/locales/en_us.json
💤 Files with no reviewable changes (1)
  • .github/workflows/codeql.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/sonarcloud-sync.sh

- Split sonar job into sonar (scan) and sonar-sync (issue creation)
- sonar job: contents: read only, runs on push and PR
- sonar-sync job: issues: write, runs only on push to develop
- Guard sync on scan success via needs.sonar.result == 'success'
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/ci.yml (1)

204-206: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Disable persisted checkout credentials in the write-capable sync job.

actions/checkout persists the GitHub token in .git/config by default. This job already supplies GH_TOKEN explicitly and does not need Git authentication, so add persist-credentials: false to reduce accidental credential exposure.

Proposed fix
       - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
         with:
           fetch-depth: 0
+          persist-credentials: false

Zizmor identified this credential-persistence path in the changed checkout.

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

In @.github/workflows/ci.yml around lines 204 - 206, Add persist-credentials:
false to the with configuration of the actions/checkout step in the
write-capable sync job, while preserving the existing fetch-depth and explicit
GH_TOKEN usage.

Source: Linters/SAST tools

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

Inline comments:
In @.github/workflows/ci.yml:
- Around line 189-199: Update the Sonar scan step identified by id sonar-scan so
continue-on-error is enabled only for pull request events, while scans on pushes
remain blocking. Preserve the existing sonar-sync dependency and condition so
synchronization runs only after a successful push scan.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 204-206: Add persist-credentials: false to the with configuration
of the actions/checkout step in the write-capable sync job, while preserving the
existing fetch-depth and explicit GH_TOKEN usage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6227ca59-7ad2-4be4-9acc-2e3fe6661c84

📥 Commits

Reviewing files that changed from the base of the PR and between 13e73c6 and ffe30ab.

📒 Files selected for processing (1)
  • .github/workflows/ci.yml

Comment thread .github/workflows/ci.yml
Comment on lines +189 to +199
id: sonar-scan
continue-on-error: true
uses: SonarSource/sonarqube-scan-action@7006c4492b2e0ee0f816d36501671557c97f5995 # v8.1.0
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}

sonar-sync:
name: Sync SonarCloud findings
runs-on: ubuntu-latest
needs: sonar
if: github.event_name == 'push' && github.ref == 'refs/heads/develop' && needs.sonar.result == 'success'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files .github/workflows/ci.yml
wc -l .github/workflows/ci.yml
sed -n '160,230p' .github/workflows/ci.yml

Repository: BillyOutlast/drop

Length of output: 2555


Don't let the Sonar scan be non-blocking on push

continue-on-error: true lets the sonar job succeed even when the scan fails, so sonar-sync can run against stale or incomplete findings and update GitHub Issues incorrectly. Use the non-blocking behavior only for pull requests.

Proposed fix
-        continue-on-error: true
+        continue-on-error: ${{ github.event_name == 'pull_request' }}
📝 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
id: sonar-scan
continue-on-error: true
uses: SonarSource/sonarqube-scan-action@7006c4492b2e0ee0f816d36501671557c97f5995 # v8.1.0
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
sonar-sync:
name: Sync SonarCloud findings
runs-on: ubuntu-latest
needs: sonar
if: github.event_name == 'push' && github.ref == 'refs/heads/develop' && needs.sonar.result == 'success'
continue-on-error: ${{ github.event_name == 'pull_request' }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 189 - 199, Update the Sonar scan step
identified by id sonar-scan so continue-on-error is enabled only for pull
request events, while scans on pushes remain blocking. Preserve the existing
sonar-sync dependency and condition so synchronization runs only after a
successful push scan.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant