mirror of
https://github.com/suitenumerique/docs.git
synced 2026-05-09 08:32:12 +02:00
⚗️(front) conditionaly install blocknote xl packages
The blocknote xl packages are licensed under AGPL v3. We want to allow a reuser to build the project without them. For this, in a first step we don't list these packages in the dependencies but install them using a postinstall script. This script is a node script looking in every package.json files under the apps directory, look if an `extraDependencies` key exists and if yes hten will install the listed dependencies after prompting the user if wants or not to install them. Also an environment variable AUTO_INSTALL_EXTRA_DEPS can be used to explicitly install all the dependencies or to explicitly not install them. This will help to build an image with and without these dependencies. Moreover we also need thisin a CI context.
This commit is contained in:
2
.github/workflows/dependencies.yml
vendored
2
.github/workflows/dependencies.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
node-version: ${{ inputs.node_version }}
|
||||
- name: Install dependencies
|
||||
if: steps.front-node_modules.outputs.cache-hit != 'true'
|
||||
run: cd src/frontend/ && yarn install --frozen-lockfile
|
||||
run: cd src/frontend/ && AUTO_INSTALL_EXTRA_DEPS=true yarn install --frozen-lockfile
|
||||
- name: Cache install frontend
|
||||
if: steps.front-node_modules.outputs.cache-hit != 'true'
|
||||
uses: actions/cache@v4
|
||||
|
||||
@@ -158,6 +158,7 @@ services:
|
||||
Y_PROVIDER_URL: "ws://localhost:4444"
|
||||
MEDIA_URL: "http://localhost:8083"
|
||||
SW_DEACTIVATED: "true"
|
||||
AUTO_INSTALL_EXTRA_DEPS: "true"
|
||||
image: impress:frontend-development
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
FROM node:20-alpine AS frontend-deps
|
||||
|
||||
ARG AUTO_INSTALL_EXTRA_DEPS=false
|
||||
|
||||
WORKDIR /home/frontend/
|
||||
|
||||
COPY ./src/frontend/package.json ./package.json
|
||||
COPY ./src/frontend/bin/conditional-install.js ./bin/conditional-install.js
|
||||
COPY ./src/frontend/yarn.lock ./yarn.lock
|
||||
COPY ./src/frontend/apps/impress/package.json ./apps/impress/package.json
|
||||
COPY ./src/frontend/packages/eslint-config-impress/package.json ./packages/eslint-config-impress/package.json
|
||||
|
||||
RUN yarn install --frozen-lockfile
|
||||
RUN AUTO_INSTALL_EXTRA_DEPS=${AUTO_INSTALL_EXTRA_DEPS} yarn install --frozen-lockfile
|
||||
|
||||
COPY .dockerignore ./.dockerignore
|
||||
COPY ./src/frontend/.prettierrc.js ./.prettierrc.js
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
"@blocknote/core": "0.23.2-hotfix.0",
|
||||
"@blocknote/mantine": "0.23.2-hotfix.0",
|
||||
"@blocknote/react": "0.23.2-hotfix.0",
|
||||
"@blocknote/xl-docx-exporter": "0.23.2-hotfix.0",
|
||||
"@blocknote/xl-pdf-exporter": "0.23.2-hotfix.0",
|
||||
"@fontsource/material-icons": "5.2.5",
|
||||
"@gouvfr-lasuite/integration": "1.0.2",
|
||||
"@gouvfr-lasuite/ui-kit": "0.1.3",
|
||||
@@ -79,5 +77,9 @@
|
||||
"typescript": "*",
|
||||
"webpack": "5.98.0",
|
||||
"workbox-webpack-plugin": "7.1.0"
|
||||
},
|
||||
"extraDependencies": {
|
||||
"@blocknote/xl-docx-exporter": "0.23.2-hotfix.0",
|
||||
"@blocknote/xl-pdf-exporter": "0.23.2-hotfix.0"
|
||||
}
|
||||
}
|
||||
|
||||
139
src/frontend/bin/conditional-install.js
Normal file
139
src/frontend/bin/conditional-install.js
Normal file
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
const readline = require('readline');
|
||||
|
||||
// Check if AUTO_INSTALL_EXTRA_DEPS is explicitly set to false
|
||||
if (process.env.AUTO_INSTALL_EXTRA_DEPS === 'false') {
|
||||
console.log('AUTO_INSTALL_EXTRA_DEPS is set to false, skipping script execution');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Get the workspace root directory
|
||||
const workspaceRoot = process.cwd();
|
||||
|
||||
// Check if AUTO_INSTALL_EXTRA_DEPS environment variable is set to bypass prompts
|
||||
const autoMode = process.env.AUTO_INSTALL_EXTRA_DEPS === 'true';
|
||||
|
||||
// Create readline interface for user prompts
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
// Function to prompt user for confirmation
|
||||
function promptUser(question) {
|
||||
return new Promise((resolve) => {
|
||||
rl.question(question, (answer) => {
|
||||
resolve(answer.toLowerCase().startsWith('y'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Function to find all package.json files in the apps directory
|
||||
function findPackageJsonFiles(directory) {
|
||||
const appsDir = path.join(workspaceRoot, directory);
|
||||
|
||||
// Check if the directory exists
|
||||
if (!fs.existsSync(appsDir)) {
|
||||
console.log(`Directory ${directory} does not exist, skipping...`);
|
||||
return [];
|
||||
}
|
||||
|
||||
const packageJsonFiles = [];
|
||||
|
||||
// Read all items in the directory
|
||||
const items = fs.readdirSync(appsDir);
|
||||
|
||||
for (const item of items) {
|
||||
const itemPath = path.join(appsDir, item);
|
||||
const stat = fs.statSync(itemPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
// Check if this directory has a package.json
|
||||
const packageJsonPath = path.join(itemPath, 'package.json');
|
||||
if (fs.existsSync(packageJsonPath)) {
|
||||
packageJsonFiles.push(packageJsonPath);
|
||||
// Skip searching in subdirectories once a package.json is found
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only search subdirectories if no package.json was found in this directory
|
||||
packageJsonFiles.push(...findPackageJsonFiles(path.join(directory, item)));
|
||||
}
|
||||
}
|
||||
|
||||
return packageJsonFiles;
|
||||
}
|
||||
|
||||
// Find all package.json files in the apps directory
|
||||
const packageJsonFiles = findPackageJsonFiles('apps');
|
||||
|
||||
if (packageJsonFiles.length === 0) {
|
||||
console.log('No package.json files found in the apps directory');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
console.log(`Found ${packageJsonFiles.length} package.json files in the apps directory`);
|
||||
|
||||
// Process each package.json file
|
||||
async function processPackageJsonFiles() {
|
||||
for (const packageJsonPath of packageJsonFiles) {
|
||||
try {
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
||||
|
||||
// Check if extraDependencies exists
|
||||
if (packageJson.extraDependencies && Object.keys(packageJson.extraDependencies).length > 0) {
|
||||
console.log(`Found extraDependencies in ${packageJsonPath}, installing...`);
|
||||
|
||||
// Process each dependency individually
|
||||
for (const [pkg, version] of Object.entries(packageJson.extraDependencies)) {
|
||||
const dependencyToInstall = `${pkg}@${version}`;
|
||||
|
||||
// Prompt user if not in auto mode
|
||||
let shouldInstall = autoMode;
|
||||
if (!autoMode) {
|
||||
shouldInstall = await promptUser(`
|
||||
Do you want to install ${dependencyToInstall}? (y/n):
|
||||
Note that these packages are dual-licensed by Blocknotejs
|
||||
under AGPL-3.0 or a proprietary license. If you choose
|
||||
to install them, please ensure you fulfill your licensing
|
||||
obligations with respect to BlockNoteJS
|
||||
`);
|
||||
}
|
||||
|
||||
if (shouldInstall) {
|
||||
// Install the dependency using npm install
|
||||
try {
|
||||
console.log(`Installing: ${dependencyToInstall}`);
|
||||
execSync(`npm install --no-save --ignore-scripts --no-audit ${dependencyToInstall}`, { stdio: 'inherit' });
|
||||
console.log(`Extra dependency ${dependencyToInstall} installed successfully`);
|
||||
} catch (error) {
|
||||
console.error(`Failed to install extra dependency ${dependencyToInstall}:`, error.message);
|
||||
// Continue with other dependencies even if one fails
|
||||
}
|
||||
} else {
|
||||
console.log(`Skipping installation of ${dependencyToInstall}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(`No extraDependencies found in ${packageJsonPath}, skipping installation`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error reading or parsing ${packageJsonPath}:`, error.message);
|
||||
// Continue with other package.json files even if one fails
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Finished processing all package.json files');
|
||||
rl.close();
|
||||
}
|
||||
|
||||
// Run the async function
|
||||
processPackageJsonFiles().catch(error => {
|
||||
console.error('An error occurred:', error);
|
||||
rl.close();
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -25,7 +25,8 @@
|
||||
"i18n:deploy": "yarn I18N run format-deploy && yarn APP_IMPRESS prettier",
|
||||
"i18n:test": "yarn I18N run test",
|
||||
"test": "yarn server:test && yarn app:test",
|
||||
"server:test": "yarn COLLABORATION_SERVER run test"
|
||||
"server:test": "yarn COLLABORATION_SERVER run test",
|
||||
"postinstall": "node ./bin/conditional-install.js"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/node": "22.13.9",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user