Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
CHANGELOG for 1.x
===================
## v1.8.1 - (2026-10-12)
### Added
- `docs/rules.md` : the project rules checked by Smart App (PHP, PHPStan, JavaScript), each with what is checked and why, including the
reasons why `npm` is our main package manager, why Yarn is excluded and why pnpm is only accepted.

### Changed
- `docs/front_code_validation.md` : commands moved from `yarn` to `npm` (`npm install --save-dev`, `npm run`, `npx`), with a reminder
that `npm` is the package manager declared in `packageManager`, linking to [docs/rules.md](docs/rules.md#jspackage-manager).

## v1.8.0 - (2026-09-23)
### TODO When updating
The DAST scans (OWASP ZAP) moved to the stack-agnostic Standard Security Gitlab Package
Expand Down
29 changes: 16 additions & 13 deletions docs/front_code_validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ without Symfony (Vanilla Javascript, Typescript, Full Vue, Vue SPA, ...).
> **Documentation only.** This bundle ships no front configuration: nothing below is copied by the recipe. This page states the
> principle and the reference setup each project type applies.

> **Package manager.** The commands below use `npm`, the package manager we use and declare in the `packageManager` field of
> `package.json`. See [`js.package-manager`](rules.md#jspackage-manager) for why, and for what is accepted instead.

## Tool responsibilities

| Tool | Scope |
Expand Down Expand Up @@ -82,7 +85,7 @@ This section is the framework agnostic base. Each following section adds what a
Command to run to add the dependencies to your `package.json`:

```sh
yarn add --dev eslint @eslint/js eslint-config-prettier prettier
npm install --save-dev eslint @eslint/js eslint-config-prettier prettier
```

List of the commands to add in the `package.json` for each tool, plus the global validation one:
Expand All @@ -94,7 +97,7 @@ List of the commands to add in the `package.json` for each tool, plus the global
"lint:baseline": "rm -f eslint-suppressions.json && eslint . --suppress-all",
"format": "prettier --write .",
"format:check": "prettier --check .",
"validation": "yarn lint:check; s=$?; yarn format:check && exit $s"
"validation": "npm run lint:check; s=$?; npm run format:check && exit $s"
}
```

Expand Down Expand Up @@ -177,11 +180,11 @@ export default defineConfig([

Extra packages to add:

`yarn add --dev eslint-plugin-vue vue-eslint-parser`
`npm install --save-dev eslint-plugin-vue vue-eslint-parser`

> `vue-eslint-parser`, the parser that splits a `.vue` file to expose its template and its script to ESLint, is a peer dependency
> of `eslint-plugin-vue`. It has to be declared if the project uses yarn instead of pnpm, as the former doesn't install peer deps
> by default.
> of `eslint-plugin-vue` that the config imports directly, so it is declared explicitly. npm and pnpm install peer deps by default,
> Yarn doesn't, which is one of the reasons why it is [excluded](rules.md#jspackage-manager).

Impact on the ESLint config, `.vue` added to the linted extensions and the preset spread after the JS rules:

Expand Down Expand Up @@ -221,7 +224,7 @@ that means rewriting every existing template for no functional gain, and which t

Extra package to add:

`yarn add --dev globals`
`npm install --save-dev globals`

The scope of the `lint` and `format` commands must be narrowed to the only directory holding front code, `assets`, which gives in `package.json`:

Expand All @@ -232,7 +235,7 @@ The scope of the `lint` and `format` commands must be narrowed to the only direc
"lint:baseline": "rm -f eslint-suppressions.json && eslint assets --suppress-all",
"format": "prettier --write assets",
"format:check": "prettier --check assets",
"validation": "yarn lint:check; s=$?; yarn format:check && exit $s"
"validation": "npm run lint:check; s=$?; npm run format:check && exit $s"
}
```

Expand Down Expand Up @@ -299,7 +302,7 @@ subject to both:

Extra package to add:

`yarn add --dev prettier-plugin-tailwindcss`
`npm install --save-dev prettier-plugin-tailwindcss`

The official class sorter enforces one canonical order for the utility classes, which removes any debate on where a class goes.

Expand Down Expand Up @@ -332,7 +335,7 @@ Impact on the Prettier config:

Extra package to add:

`yarn add --dev @vue/eslint-config-typescript`
`npm install --save-dev @vue/eslint-config-typescript`

[This config](https://github.com/vuejs/eslint-config-typescript), still the one of the create-vue TypeScript template, wires
`typescript-eslint` on the `.vue` files.
Expand Down Expand Up @@ -363,7 +366,7 @@ code.

- [Bulk suppressions](https://eslint.org/docs/latest/use/suppressions): `eslint-suppressions.json` counts existing violations per file
and rule, only new ones fail. Same principle as the [PHPStan baseline](phpstan.md).
- `yarn lint:baseline` regenerates it from scratch (`--suppress-all` never removes entries). Review its diff before committing.
- `npm run lint:baseline` regenerates it from scratch (`--suppress-all` never removes entries). Review its diff before committing.
- Violation fixed → entry obsolete → `lint:check` exits with code 2 → regenerate.
- Only `error` rules are recorded.

Expand All @@ -374,10 +377,10 @@ There is no proper "baseline" in Prettier but there is a similar alternative cal
The `requirePragma: true` config option restricts it to files starting with a `@format` pragma
([options](https://prettier.io/docs/options#require-pragma): "gradually transitioning large, unformatted codebases").

- Opt a file in: `yarn prettier --write --no-require-pragma --insert-pragma <files>` (`--insert-pragma` alone does nothing,
- Opt a file in: `npx prettier --write --no-require-pragma --insert-pragma <files>` (`--insert-pragma` alone does nothing,
`requirePragma` wins).
- Marker: `<!-- @format -->` in `.vue`, `/** @format */` in `.js` and `.css`.
- Then `yarn lint:baseline`: formatting fixes `vue/first-attribute-linebreak`, its entries become obsolete.
- Then `npm run lint:baseline`: formatting fixes `vue/first-attribute-linebreak`, its entries become obsolete.
- Remove the option once every file is formatted.

### Prettier: one-shot formatting commit
Expand All @@ -387,7 +390,7 @@ with few front files, low sensitivity, and few people and open branches on it. T
as every open branch will have to be rebased over the reformatted files.

1. Commit the config, merge open branches.
2. One commit with `yarn format`, nothing else.
2. One commit with `npm run format`, nothing else.
3. Safety net: `prettier --debug-check` on the same scope reports any file whose meaning might change.
4. Once merged (squash or rebase changes the hash), add the commit hash to `.git-blame-ignore-revs`. Each dev runs
`git config blame.ignoreRevsFile .git-blame-ignore-revs` (PhpStorm follows it). GitLab: *Blame preferences › Ignore specific revisions*.
Expand Down
76 changes: 76 additions & 0 deletions docs/rules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Project rules

The rules every SMARTBOOSTER repository is checked against by Smart App.

Each rule is evaluated on the files repository and ends up :
- **compliant**,
- **non compliant**,
- **not applicable** (the repository has no such file)
- **unknown** (a file is unreadable, or the production version is not declared).

Rules are grouped by category, the subject of their code (`phpstan.level` → `phpstan`). The PHP rules are not applicable without
`composer.json`, the JavaScript rules without `package.json`.

## PHP

### `php.composer-require`

**Check :** `require.php` in `composer.json` accepts the whole minor of `PHP_VERSION`, and only that one (`~8.4.0`, `8.4.*`).
A wider constraint (`>=8.1`, `^8.4`) is not compliant.

**Why :** Composer must only resolve dependencies for the PHP version that runs in production.

### `php.composer-platform`

**Check :** `config.platform.php` in `composer.json` is in the production minor (`8.4.0` for `PHP_VERSION=8.4`).

**Why :** Composer resolves dependencies for the production version, not for the one of the machine that runs the install.

## PHPStan

### `phpstan.level`

**Check :** The PHPStan config file declares `level: 10`. A level only given on the command line (Makefile, CI) does not count,
and `max` is not accepted.

**Why :** The highest level catches type errors before production. `max` moves with PHPStan versions: a level is tested before being
imposed, so we declare `10` explicitly.

See [PHPStan](phpstan.md) for the setup of a new project and the level migration workflow of a legacy one.

## JavaScript

### `js.package-manager`

**Check :** One single lock file next to `package.json`: `package-lock.json` (npm) or `pnpm-lock.yaml` (pnpm), never `yarn.lock`.
The `packageManager` field is mandatory and names the same manager as the lock (`npm@11.6.2`).

**Why :** One manager and its lock install the same dependency versions everywhere; two managers sharing a repository do not.
`packageManager` makes the choice explicit and lets Corepack pin the version.

> `npm` is the main package manager that we decide to use because it is the only one that comes natively with Node: installing
> Node gives the matching npm, with nothing else to install or to keep aligned on the Docker image, the CI and the production host.
>
> Yarn and pnpm are not shipped with Node. They go through [Corepack](https://github.com/nodejs/corepack), a shim bundled with
> Node up to 24 but opt-in (`corepack enable`) and no longer distributed from Node 25, or through a global install that we would
> have to pin everywhere. This is why `packageManager` is mandatory: it states which manager and which exact version the project
> expects, and it is what Corepack reads to pin it.
>
> **Why Yarn is excluded.** We only ever used Yarn Classic (1.x), a line that is frozen upstream: it no longer evolves, and a
> modern Yarn is not native either (Corepack, another config model). It also has rough edges we ran into: it does not install
> peer dependencies by default (see the `vue-eslint-parser` note in [front code validation](front_code_validation.md)).
>
> **Why pnpm is accepted.** We use it to try this manager on our internal projects. We do not use it on Clever Cloud instances,
> because it is not provided by default on the PHP scalers, unlike npm.

### `js.node-engine`

**Check :** `engines.node` in `package.json` accepts the major of `NODE_VERSION` and refuses the others (`24.x`, `^24.11`).

**Why :** JavaScript dependencies must be installed for the Node version that runs in production.

### `js.engine-strict`

**Check :** `engine-strict=true` in `.npmrc`.

**Why :** Without it `engines.node` is only a warning: npm installs anyway on a Node version the project refuses.
Loading