Skip to content

Add License In build#5

Merged
0suu merged 3 commits into
mainfrom
suu/AddLicenseInBuild
Nov 22, 2025
Merged

Add License In build#5
0suu merged 3 commits into
mainfrom
suu/AddLicenseInBuild

Conversation

@0suu

@0suu 0suu commented Nov 22, 2025

Copy link
Copy Markdown
Owner

No description provided.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @0suu, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a robust system for managing and distributing third-party software licenses. By automating the generation of a comprehensive license file and integrating it directly into the build and packaging process, the project ensures legal compliance and transparency regarding its dependencies. This change streamlines the maintenance of license information and makes it readily available within the application's installer.

Highlights

  • Automated License Generation: A new script (scripts/generate-licenses.js) has been added to automatically collect and format third-party dependency license information.
  • Build Integration: The license generation process is now integrated into the npm run build command, ensuring that license files are always up-to-date with the build.
  • Installer Bundling: The generated THIRD_PARTY_LICENSES.txt file, along with the root LICENSE file, is now automatically bundled into the application installer by Electron Builder.
  • Documentation Update: Both Japanese and English README files have been updated to inform users about the new license generation process and how to refresh the license list.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread package.json
Comment on lines +83 to +87
"from": "build/licenses",
"to": "licenses",
"filter": [
"THIRD_PARTY_LICENSES.txt"
]

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 Badge Generate license report before packaging

The new extraResources entry instructs electron-builder to copy build/licenses/THIRD_PARTY_LICENSES.txt, but the existing npm scripts still only call build:vite and build:electron—there is no build:licenses task or other hook that runs scripts/generate-licenses.js, and build/licenses is not present in the repo. When npm run package triggers electron-builder, it will fail with an ENOENT because the from path in this extra resource does not exist. Please wire license generation into the build/package pipeline (or commit the file) so installers can be produced.

Useful? React with 👍 / 👎.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request adds functionality to generate and include third-party licenses in the application build. It introduces a new script for license generation, adds the necessary dependency, and configures electron-builder to bundle the licenses. While the implementation is mostly correct, there is a critical issue: the main build script has not been updated to run the new license generation script, which contradicts the updated documentation and will cause the packaging step to fail. I've provided comments on the README files with details on how to resolve this.

Comment thread README.md

Electron Builder の設定 (`package.json` の `build` フィールド) により、アプリ ID や配布ターゲット、アイコンなどが制御されます。

依存ライブラリのライセンス一覧は `npm run build:licenses`(`npm run build` 内で自動実行)で `build/licenses/THIRD_PARTY_LICENSES.txt` に生成され、ルートの `LICENSE` と共にインストーラへ同梱されます。依存パッケージを更新した際はこのスクリプトを再実行してください。

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

This documentation states that npm run build:licenses is automatically executed within npm run build, but the scripts in package.json have not been updated to reflect this.

The build:licenses script needs to be defined and called from the build script. Without this change, THIRD_PARTY_LICENSES.txt will not be generated, causing electron-builder to fail during the npm run package command.

Please update package.json to integrate the license generation. For example:

"scripts": {
  ...
  "build": "npm run build:licenses && npm run build:vite && npm run build:electron",
  "build:licenses": "node scripts/generate-licenses.js",
  ...
}

Comment thread README_en.md

Electron Builder uses the configuration defined in `package.json` (`build` field) for app ID, product name, and targets.

Dependency licenses are generated via `npm run build:licenses` (automatically executed inside `npm run build`) into `build/licenses/THIRD_PARTY_LICENSES.txt`, and Electron Builder bundles that file together with the root `LICENSE` in the installers. Re-run the script after dependency changes to refresh the list.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

critical

This documentation states that npm run build:licenses is "automatically executed inside npm run build". However, the scripts in package.json have not been updated to implement this.

The build:licenses script is missing, and the main build script does not call it. This will cause the npm run package command to fail because electron-builder will not be able to find the THIRD_PARTY_LICENSES.txt file.

Please update package.json to add the build:licenses script and integrate it into the build script. For example:

"scripts": {
  ...
  "build": "npm run build:licenses && npm run build:vite && npm run build:electron",
  "build:licenses": "node scripts/generate-licenses.js",
  ...
}

@0suu

0suu commented Nov 22, 2025

Copy link
Copy Markdown
Owner Author

/gemini review

@0suu

0suu commented Nov 22, 2025

Copy link
Copy Markdown
Owner Author

@codex review

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request adds a mechanism to generate a THIRD_PARTY_LICENSES.txt file and bundle it into the application build, which is great for compliance. The implementation is solid, using license-checker and integrating it into the build process via an npm script. My review includes two suggestions for improvement: one regarding the long-term maintainability of the chosen dependency, and another to refactor the new script to use asynchronous file system operations, which is a best practice in Node.js.

Comment thread package.json Outdated
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"license-checker": "^25.0.1",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The license-checker package is a good choice for this task, but this version (25.0.1) was published several years ago and pulls in multiple deprecated dependencies (e.g., read-installed, osenv, debuglog). While it works for now, this could lead to maintenance or security issues in the future. For better long-term stability, you might consider evaluating a more modern and actively maintained alternative, such as license-checker-rseidelsohn or npm-license-crawler.

Comment on lines +1 to +72
const fs = require('fs');
const path = require('path');
const util = require('util');
const checker = require('license-checker');

const init = util.promisify(checker.init);
const projectRoot = path.resolve(__dirname, '..');
const outputDir = path.join(projectRoot, 'build', 'licenses');
const outputFile = path.join(outputDir, 'THIRD_PARTY_LICENSES.txt');
const packageJson = require(path.join(projectRoot, 'package.json'));

function readLicenseFile(filePath) {
if (!filePath) {
return '';
}

try {
return fs.readFileSync(filePath, 'utf8');
} catch (error) {
return '';
}
}

function formatPackage(pkgName, info) {
const license = Array.isArray(info.licenses)
? info.licenses.join(', ')
: info.licenses || 'UNKNOWN';
const publisher = info.publisher || 'N/A';
const repository = info.repository || info.url || 'N/A';
const licenseFile = info.licenseFile ? path.relative(projectRoot, info.licenseFile) : 'N/A';
const licenseText = (info.licenseText || readLicenseFile(info.licenseFile) || 'License text unavailable.').trim();

return [
pkgName,
`License: ${license}`,
`Publisher: ${publisher}`,
`Repository: ${repository}`,
`License file: ${licenseFile}`,
'',
licenseText,
].join('\n');
}

async function main() {
const skipSelf = packageJson.name && packageJson.version ? `${packageJson.name}@${packageJson.version}` : null;
const packages = await init({
start: projectRoot,
production: true,
licenseText: true,
});

const entries = Object.keys(packages)
.filter((pkgName) => pkgName !== skipSelf)
.sort((a, b) => a.localeCompare(b))
.map((pkgName) => formatPackage(pkgName, packages[pkgName]));

const header = [
`Third-party licenses for ${packageJson.name || 'application'} v${packageJson.version || ''}`.trim(),
`Generated at ${new Date().toISOString()}`,
'',
].join('\n');

fs.mkdirSync(outputDir, { recursive: true });
fs.writeFileSync(outputFile, `${header}${entries.join('\n\n-----\n\n')}\n`, 'utf8');
console.log(`Saved license report for ${entries.length} dependencies to ${path.relative(projectRoot, outputFile)}`);
}

main().catch((error) => {
console.error('[license-generation] Failed to generate license report.');
console.error(error);
process.exit(1);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

While using synchronous file system methods (readFileSync, mkdirSync, writeFileSync) is acceptable in a simple build script, it's a good practice in Node.js to use their asynchronous counterparts to avoid blocking the event loop. Since this script is already using async/await, you can refactor it to use fs.promises for better consistency and performance, especially when reading multiple license files.

const fs = require('fs').promises;
const path = require('path');
const util = require('util');
const checker = require('license-checker');

const init = util.promisify(checker.init);
const projectRoot = path.resolve(__dirname, '..');
const outputDir = path.join(projectRoot, 'build', 'licenses');
const outputFile = path.join(outputDir, 'THIRD_PARTY_LICENSES.txt');
const packageJson = require(path.join(projectRoot, 'package.json'));

async function readLicenseFile(filePath) {
  if (!filePath) {
    return '';
  }

  try {
    return await fs.readFile(filePath, 'utf8');
  } catch (error) {
    // It's okay if a license file doesn't exist, so we don't need to log this error.
    return '';
  }
}

async function formatPackage(pkgName, info) {
  const license = Array.isArray(info.licenses)
    ? info.licenses.join(', ')
    : info.licenses || 'UNKNOWN';
  const publisher = info.publisher || 'N/A';
  const repository = info.repository || info.url || 'N/A';
  const licenseFile = info.licenseFile ? path.relative(projectRoot, info.licenseFile) : 'N/A';

  const licenseTextFromFile = await readLicenseFile(info.licenseFile);
  const licenseText = (info.licenseText || licenseTextFromFile || 'License text unavailable.').trim();

  return [
    pkgName,
    `License: ${license}`,
    `Publisher: ${publisher}`,
    `Repository: ${repository}`,
    `License file: ${licenseFile}`,
    '',
    licenseText,
  ].join('\n');
}

async function main() {
  const skipSelf = packageJson.name && packageJson.version ? `${packageJson.name}@${packageJson.version}` : null;
  const packages = await init({
    start: projectRoot,
    production: true,
    licenseText: true,
  });

  const packageNames = Object.keys(packages)
    .filter((pkgName) => pkgName !== skipSelf)
    .sort((a, b) => a.localeCompare(b));

  const entries = await Promise.all(
    packageNames.map((pkgName) => formatPackage(pkgName, packages[pkgName]))
  );

  const header = [
    `Third-party licenses for ${packageJson.name || 'application'} v${packageJson.version || ''}`.trim(),
    `Generated at ${new Date().toISOString()}`,
    '',
  ].join('\n');

  await fs.mkdir(outputDir, { recursive: true });
  await fs.writeFile(outputFile, `${header}${entries.join('\n\n-----\n\n')}\n`, 'utf8');
  console.log(`Saved license report for ${entries.length} dependencies to ${path.relative(projectRoot, outputFile)}`);
}

main().catch((error) => {
  console.error('[license-generation] Failed to generate license report.');
  console.error(error);
  process.exit(1);
});

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +46 to +49
const packages = await init({
start: projectRoot,
production: true,
licenseText: true,

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 Badge License report skips bundled dev dependencies

generate-licenses.js runs license-checker with production: true, which omits devDependencies. In this repo React/ReactDOM live in devDependencies (package.json) but their code is bundled into the renderer output. Running npm run build now produces build/licenses/THIRD_PARTY_LICENSES.txt without those licenses, so installers miss notices for packages actually shipped with the app.

Useful? React with 👍 / 👎.

@0suu

0suu commented Nov 22, 2025

Copy link
Copy Markdown
Owner Author

/gemini review

@0suu

0suu commented Nov 22, 2025

Copy link
Copy Markdown
Owner Author

/codex review

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a mechanism to automatically generate and bundle third-party dependency licenses into the application build. This is achieved by adding the license-checker-rseidelsohn package and a new Node.js script (scripts/generate-licenses.js) that runs as part of the npm run build command. The changes also include updating the README files to document this new process and correctly categorizing react and react-dom as runtime dependencies.

The implementation is well-done and robust. I have one suggestion to improve the error logging in the new license generation script to make it easier to debug potential issues with missing license files in the future. Overall, this is a great addition for license compliance.

try {
return fs.readFileSync(filePath, 'utf8');
} catch (error) {
return '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The current implementation silently ignores errors when reading a license file. While this prevents the build from failing, it hides potentially important issues, such as a license file being referenced but missing or unreadable. It would be more robust to log a warning to the console when an error occurs. This will improve the debuggability of the license generation process without breaking the build.

    console.warn(`[license-generation] Could not read license file at ${filePath}: ${error.message}`);
    return '';

@0suu

0suu commented Nov 22, 2025

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@0suu 0suu merged commit a676dbc into main Nov 22, 2025
2 checks passed
@0suu 0suu deleted the suu/AddLicenseInBuild branch November 22, 2025 23:46
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