From 768e65caa4c6a4c408441f0938463bdd63ed20f4 Mon Sep 17 00:00:00 2001 From: Minsu Lee Date: Mon, 14 Sep 2026 16:30:27 +0900 Subject: [PATCH] chore(ci): scope Sonar and Codacy off the generated skill bundles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both services analyse every push through their GitHub App — no workflow invokes either — so `skills/spring-docs/scripts/docs.mjs` was being scored as ordinary source. It is `scripts/docs.ts` run through the bundler and committed for the `npx skills` channel, so analysing it reports the same program twice: the whole file registers as duplication against its own source (7.7% on new code, over a 3% gate), and the `var` declarations Bun emits cost a reliability rating that no edit can recover, because `build:skill:check` byte-compares the bundle against a fresh build. `eslint.config.js` already ignored the directory for exactly this reason; the two analysers now do the same. The file names are not interchangeable. SonarQube Cloud runs in Automatic Analysis mode, which reads `.sonarcloud.properties` and explicitly ignores `sonar-project.properties`, accepts no wildcards, and honours only the copy on the default branch — so this half cannot take effect until it lands there. Codacy reads `.codacy.yml`, and additions are honoured on the pull request that makes them. What this does not fix: Codacy's ESLint runs its own rule set rather than this repository's, so `detect-non-literal-fs-filename` from `eslint-plugin-security` — a plugin absent from our dependency tree — still fires on `scripts/docs.ts`, whose whole job is building and reading cache paths. Codacy detects `eslint.config.js` for ESLint v9, but activating it is a toggle on the repository's Code patterns page rather than a change that can be committed. Records both, and the fact that neither check gates a merge, in gotchas. Refs #19 --- .codacy.yml | 14 ++++++++++++++ .please/docs/knowledge/gotchas.md | 14 ++++++++++++++ .sonarcloud.properties | 23 +++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 .codacy.yml create mode 100644 .sonarcloud.properties diff --git a/.codacy.yml b/.codacy.yml new file mode 100644 index 0000000..07d8b4f --- /dev/null +++ b/.codacy.yml @@ -0,0 +1,14 @@ +--- +# Codacy analyses this repository through its GitHub App; no workflow invokes +# it. Unlike SonarQube Cloud, additions here are honoured on the pull request +# that makes them — only removals wait for the default branch. +# +# Note that once this file exists, the "Ignored files" settings in the Codacy UI +# no longer apply: everything must be ignored from here. +exclude_paths: + # Generated by `bun run build:skill` from `scripts/*.ts` and committed, because + # the `npx skills` install channel copies only the skill directory and runs no + # dependency install. They are the same program as their sources, so analysing + # them reports every finding twice and counts the whole bundle as duplication. + # `eslint.config.js` and `.sonarcloud.properties` exclude the same directory. + - 'skills/*/scripts/**' diff --git a/.please/docs/knowledge/gotchas.md b/.please/docs/knowledge/gotchas.md index ca0501d..9641573 100644 --- a/.please/docs/knowledge/gotchas.md +++ b/.please/docs/knowledge/gotchas.md @@ -18,6 +18,20 @@ - **lint-staged + `--max-warnings 0` + ignored files**: when a staged path falls under eslint's ignore-list, eslint emits a "File ignored because of a matching ignore pattern" *warning* that trips `--max-warnings 0` and fails the pre-commit hook. Add `--no-warn-ignored` to the lint-staged eslint command to suppress. +## Static analysis (SonarQube Cloud, Codacy) + +Neither service is invoked by a workflow — both analyse every push through their GitHub App. That changes where their configuration lives and when it takes effect. + +- **SonarQube Cloud is in Automatic Analysis mode, which reads `.sonarcloud.properties` and ignores `sonar-project.properties`.** The docs are explicit that the two files are different and that a `sonar-project.properties` in an imported project is ignored. Three further constraints: only the copy on the **default branch** applies (a change does not affect the PR that makes it), **wildcards are not allowed** in the values, and where the file and the SonarQube Cloud UI disagree the **file wins** — so an entry that matches nothing cannot be corrected from the UI while it is still there. + +- **Codacy reads `.codacy.yml` (or `.codacy.yaml`), and the first line must be `---`.** Additions are honoured on the PR that makes them; only removals wait for the default branch. Once the file exists, the UI's "Ignored files" settings stop applying. Validate before pushing: `docker run --rm -v "$(pwd)":/src codacy/codacy-analysis-cli validate-configuration --directory /src`. + +- **Codacy's ESLint runs its own rule set, not this repo's, unless the Code patterns UI toggle says otherwise.** That is why `bun run lint` is clean while Codacy reports dozens of `Found from package "node:fs" with non literal argument` — the rule is `detect-non-literal-fs-filename` from `eslint-plugin-security`, which is not in this repo's dependency tree at all. On a module whose job is building and reading cache paths it fires on nearly every line. Codacy detects `eslint.config.js` for ESLint v9, but using it requires activating the per-tool "Configuration file" toggle on the repository's Code patterns page — a UI action, not a repo change. + +- **The committed skill bundles must be excluded from both.** `skills/*/scripts/*.mjs` is generated from `scripts/*.ts` and committed for the `npx skills` channel, so analysing it scores the same program twice: full-file duplication against its source, plus the `var` declarations Bun emits, which cannot be edited away because `build:skill:check` byte-compares the bundle. `eslint.config.js` already ignored it; `.sonarcloud.properties` and `.codacy.yml` now do too. + +- **Neither check blocks a merge.** The `main` ruleset carries no `required_status_checks` rule — only `deletion`, `non_fast_forward`, and a `pull_request` rule with `required_approving_review_count: 0`, `allowed_merge_methods: ["squash"]`, and `required_review_thread_resolution: true`. A PR showing `mergeStateStatus: BLOCKED` on green CI is almost always an **unresolved review thread**, not a failing analyser. Auto-merge cannot be armed at all: the repository has `allow_auto_merge: false`. + ## Repo / process - **Husky 9 pre-commit hook**: just `bunx lint-staged` on a single line. No shebang, no `set -e` — the `_/h` wrapper handles shell setup. Adding the legacy boilerplate is harmless but stale. diff --git a/.sonarcloud.properties b/.sonarcloud.properties new file mode 100644 index 0000000..dca9717 --- /dev/null +++ b/.sonarcloud.properties @@ -0,0 +1,23 @@ +# SonarQube Cloud runs here in Automatic Analysis mode — no workflow invokes a +# scanner, the GitHub App analyses every push on its own. That mode reads this +# file and ignores `sonar-project.properties`, and it accepts no wildcards in +# these values, so paths are written as plain directory prefixes. +# +# Two consequences worth knowing before editing: +# - Only the copy on the default branch takes effect. A change here does not +# alter the analysis of the pull request that makes it; it applies once +# merged. +# - Where this file and the SonarQube Cloud UI disagree, this file wins. An +# entry that matches nothing therefore cannot be corrected from the UI while +# it is still here. + +# Generated by `bun run build:skill` from `scripts/*.ts`, committed because the +# `npx skills` install channel copies only the skill directory and runs no +# dependency install. Analysing them scores the same program twice: every line +# of `scripts/docs.ts` reappears in the bundle, which read as 7.7% duplication +# on new code, and the `var` declarations Bun emits cost a reliability rating +# that no edit can recover — `bun run build:skill:check` byte-compares the +# bundle against a fresh build, so hand-editing it fails CI. +# `eslint.config.js` ignores the same directory, for the same reason. +sonar.exclusions=skills/spring-docs/scripts/ +sonar.cpd.exclusions=skills/spring-docs/scripts/