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
46 changes: 23 additions & 23 deletions scripts/check-licences.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@
* Écrit parce que ce fichier est une affirmation juridique, et qu'une affirmation que
* personne ne revérifie dérive à la première montée de version.
*
* CE FICHIER EST PARTAGÉ À L'IDENTIQUE par map3D, panels et IA Studio. La liste blanche,
* CE FICHIER EST PARTAGÉ À L'IDENTIQUE par map3D, panels et AI Desktop Studio. La liste blanche,
* les paquets embarqués et la nature du dépôt vivent dans `repo.config.json`.
*/
import { readFileSync, existsSync } from 'node:fs'
import { execFileSync } from 'node:child_process'
import { resolve } from 'node:path'

const root = resolve(import.meta.dirname, '..')
Expand Down Expand Up @@ -54,37 +53,35 @@ for (const nom of EMBARQUES) {
if (!propre.devDependencies?.[nom]) problemes.push(`${nom} est déclaré embarqué mais n'est pas installé.`)
}

/** La licence qu'un paquet déclare, lue dans l'arbre installé. */
/**
* La licence qu'un paquet déclare, par le lien que le gestionnaire pose pour toute dépendance
* déclarée — alias `npm:` compris. Le balayage de `node_modules/.pnpm` qui la précédait s'arrêtait
* un segment trop haut, et ne voyait aucun paquet scopé.
*/
function licenceDe(nom) {
try {
const trouves = execFileSync('find', [
'node_modules/.pnpm',
'-maxdepth',
'4',
'-path',
`*/node_modules/${nom}/package.json`,
])
.toString()
.split('\n')
.filter(Boolean)

if (trouves.length === 0) return null
return JSON.parse(readFileSync(trouves[0], 'utf8')).license ?? null
return JSON.parse(readFileSync(resolve(root, 'node_modules', nom, 'package.json'), 'utf8'))
.license ?? null
} catch {
return null
}
}

const declarees = [
const installees = [
...Object.keys(propre.dependencies ?? {}),
...Object.keys(propre.devDependencies ?? {}),
...Object.keys(propre.peerDependencies ?? {}),
]
// Une pair est déclarée pour le consommateur, et le gestionnaire n'installe pas celles qui sont
// optionnelles : absente ici, elle n'a rien à juger. Ce que CE dépôt installe, si.
const declarees = [...installees, ...Object.keys(propre.peerDependencies ?? {})]
const lues = declarees.map(nom => [nom, licenceDe(nom)])

for (const nom of declarees) {
const licence = licenceDe(nom)
if (licence === null) continue // pas installé ici ; rien à juger
if (!AUTORISEES.has(licence)) problemes.push(`${nom} est en ${licence}, absent de la liste blanche.`)
for (const [nom, licence] of lues) {
// Taire l'échec de lecture est ce qui faisait passer pour jugé tout paquet que la lecture ratait.
if (licence === null && installees.includes(nom))
problemes.push(`${nom} est déclaré mais sa licence est illisible : paquet absent, ou sans champ « license ».`)
else if (licence !== null && !AUTORISEES.has(licence))
problemes.push(`${nom} est en ${licence}, absent de la liste blanche.`)
}

if (problemes.length > 0) {
Expand All @@ -93,4 +90,7 @@ if (problemes.length > 0) {
process.exit(1)
}

console.log(`Licences contrôlées — ${declarees.length} paquets, tous permissifs, mentions présentes.`)
const jugees = lues.filter(([, licence]) => licence !== null).length
console.log(
`Licences contrôlées — ${jugees} paquets lus sur ${declarees.length} déclarés, tous permissifs, mentions présentes.`,
)
8 changes: 8 additions & 0 deletions site/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
<script type="application/ld+json">
{{jsonld}}
</script>
<!-- Mesure d'audience. Le bandeau de consentement et le chargement de Google Analytics
tiennent dans un seul fichier, servi par www.pasquelin.com et partagé par les quatre
sites : une correction s'y fait une fois, pas quatre. Rien n'est demandé à Google avant
un accord explicite du visiteur, et le panneau emprunte les couleurs de cette page.
L'identifiant de mesure n'est pas un secret — il est public dans toute page qui le
porte. Source, traductions et tests : dépôt `pasquelin/site`, `public/shared/`. -->
<script defer src="https://www.pasquelin.com/shared/consent.v1.js" data-ga="G-X64BG5H958"></script>

</head>

<body>
Expand Down
Loading