Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add check for files in qiskit_bot.yaml #1375

Merged
merged 7 commits into from
May 15, 2024
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
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ jobs:
run: npm run check:metadata
- name: Spellcheck
run: npm run check:spelling
- name: Check Qiskit bot config
run: npm run check:qiskit-bot
- name: Internal link checker
run: npm run check:internal-links
- name: Check orphaned pages
Expand Down
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
"author": "Qiskit Development Team",
"license": "Apache-2.0",
"scripts": {
"check": "npm run check:metadata && npm run check:spelling && npm run check:internal-links && npm run check:orphan-pages && npm run check:fmt",
"check": "npm run check:qiskit-bot && check:metadata && npm run check:spelling && npm run check:internal-links && npm run check:orphan-pages && npm run check:fmt",
"check:metadata": "node -r esbuild-register scripts/commands/checkMetadata.ts",
"check:spelling": "cspell --relative --no-progress docs/**/*.md* docs/api/**/*.md* --config cspell/cSpell.json",
"check:fmt": "prettier --check .",
"check:internal-links": "node -r esbuild-register scripts/commands/checkInternalLinks.ts",
"check:external-links": "node -r esbuild-register scripts/commands/checkExternalLinks.ts",
"check:pages-render": "node -r esbuild-register scripts/commands/checkPagesRender.ts",
"check:orphan-pages": "node -r esbuild-register scripts/commands/checkOrphanPages.ts",
"check:qiskit-bot": "node -r esbuild-register scripts/commands/checkQiskitBotFiles.ts",
"check:stale-images": "node -r esbuild-register scripts/commands/checkStaleImages.ts",
"fmt": "prettier --write .",
"test": "jest",
Expand All @@ -25,6 +26,7 @@
"@swc/jest": "^0.2.29",
"@types/fast-levenshtein": "^0.0.4",
"@types/jest": "^29.5.5",
"@types/js-yaml": "^4.0.9",
"@types/lodash": "^4.14.198",
"@types/node": "^20.6.2",
"@types/yargs": "^17.0.28",
Expand Down
128 changes: 128 additions & 0 deletions scripts/commands/checkQiskitBotFiles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// This code is a Qiskit project.
//
// (C) Copyright IBM 2024.
//
// This code is licensed under the Apache License, Version 2.0. You may
// obtain a copy of this license in the LICENSE file in the root directory
// of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
//
// Any modifications or derivative works of this code must retain this
// copyright notice, and modified files need to carry a notice indicating
// that they have been altered from the originals.

import fs from "fs/promises";
import path from "path";
import { load } from "js-yaml";
import { globby } from "globby";

const ALLOWED_OWNERLESS_FILES = new Set([
"docs/start/_toc",
"docs/build/_toc",
"docs/build/bit-ordering",
"docs/build/operators-overview",
"docs/build/save-circuits",
"docs/transpile/_toc",
"docs/transpile/create-a-transpiler-plugin",
"docs/transpile/custom-backend",
"docs/transpile/transpiler-plugins",
"docs/verify/_toc",
"docs/verify/local-testing-mode",
"docs/verify/plot-quantum-states",
"docs/verify/using-ibm-quantum-simulators",
"docs/run/_toc",
"docs/run/circuit-execution",
"docs/run/configure-runtime-compilation",
"docs/run/execution-modes-faq",
"docs/run/execution-modes",
"docs/run/native-gates",
"docs/run/save-jobs",
"docs/run/visualize-results",
]);

const ALLOWED_NONEXISTENT_FILES = new Set([
"docs/build/qubit-order",
"docs/build/operators_overview",
"docs/run/reserve-system-time",
"docs/migration-guides/index",
"docs/migration-guides/qiskit-runtime",
"docs/migration-guides/qiskit-runtime-examples",
"docs/migration-guides/qiskit-quantum-instance",
"docs/migration-guides/qiskit-algorithms-module",
"docs/migration-guides/qiskit-opflow-module",
]);

const GLOBS = [
"docs/start/*",
arnaucasau marked this conversation as resolved.
Show resolved Hide resolved
"docs/build/*",
"docs/transpile/*",
"docs/verify/*",
"docs/run/*",
"docs/migration-guides/*",
"docs/guides/*",
];

async function main() {
const qiskitBotFiles = await getQiskitBotFiles();
const filesToCheck = await getFilesToCheck();

const missingFiles = filesToCheck.filter(
(file) =>
!qiskitBotFiles.includes(file) && !ALLOWED_OWNERLESS_FILES.has(file),
);
const leftoverFiles = qiskitBotFiles.filter(
(file) =>
!filesToCheck.includes(file) && !ALLOWED_NONEXISTENT_FILES.has(file),
);

if (missingFiles.length > 0) showMissingFilesMessage(missingFiles);

if (leftoverFiles.length > 0) showLeftoverFilesMessage(leftoverFiles);

if (missingFiles.length == 0 && leftoverFiles.length == 0) {
console.log("All files have an owner in the Qiskit bot config ✅\n");
} else {
process.exit(1);
}
}

async function getQiskitBotFiles(): Promise<string[]> {
const qiskitBotConfig = "qiskit_bot.yaml";
const yaml = load(await fs.readFile(qiskitBotConfig, "utf8")) as {
notifications: { [id: string]: string[] };
};
return Object.keys(yaml.notifications).sort();
}

async function getFilesToCheck(): Promise<string[]> {
return (await globby(GLOBS)).map((file) => removeFileExtension(file)).sort();
}

function removeFileExtension(file: string): string {
const parsed = path.parse(file);
return `${parsed.dir}/${parsed.name}`;
}

function showMissingFilesMessage(missingFiles: string[]): void {
console.error(
"The following files don't have an owner in `qiskit_bot.yaml`:\n",
);
missingFiles.forEach((file) => console.error(`❌ ${file}`));

console.error(
"\nAdd an owner to the files in qiskit_bot.yaml if they are new, or update the file names in qiskit_bot.yaml if the were renamed.",
"If you don't want them to be tracked by the qiskit bot, you can append the files to the `ALLOWED_OWNERLESS_FILES` list at the beginning of `scripts/commands/checkQiskitBotFiles.ts`.\n",
);
}

function showLeftoverFilesMessage(leftoverFiles: string[]): void {
console.error(
"The following files don't exist, but they have an entry in `qiskit_bot.yaml`:\n",
);
leftoverFiles.forEach((file) => console.error(`❔ ${file}`));
console.error(
"\nRemove the files from the qiskit_bot.yaml, or rename the file in qiskit_bot.yaml if the file was renamed.",
"If the files will exist in the future, you can append the files to the `ALLOWED_NONEXISTENT_FILES` list at the beginning of `scripts/commands/checkQiskitBotFiles.ts`.\n",
);
}

main().then(() => process.exit());
Loading