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

Extend the API generation script to generate dev versions #779

Merged
merged 8 commits into from
Feb 8, 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/extended-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
npm run check:links --
--qiskit-release-notes
--current-apis
--dev-apis
--historical-apis
--skip-broken-historical
--external
Expand All @@ -57,4 +58,5 @@ jobs:
npm run check-pages-render --
--qiskit-release-notes
--current-apis
--dev-apis
if: ${{ !cancelled() }}
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ npm run check:links -- --external

# By default, only the non-API docs are checked. You can add any of the
# below arguments to also check API docs and/or Qiskit release notes.
npm run check:links -- --current-apis --historical-apis --qiskit-release-notes
npm run check:links -- --current-apis --dev-apis --historical-apis --qiskit-release-notes

# However, `--historical-apis` currently has failing versions, so you may
# want to add `--skip-broken-historical`.
Expand Down Expand Up @@ -227,7 +227,7 @@ To check that all the non-API docs render:
1. Start up the local preview with `./start` by following the instructions at [Preview the docs locally](#preview-the-docs-locally)
2. In a new tab, `npm run check-pages-render`

You can also check that API docs and translations render by using any of these arguments: `npm run check-pages-render -- --qiskit-release-notes --current-apis --historical-apis --translations`. Warning that this is exponentially slower.
You can also check that API docs and translations render by using any of these arguments: `npm run check-pages-render -- --qiskit-release-notes --current-apis --dev-apis --historical-apis --translations`. Warning that this is exponentially slower.

CI will check on every PR that non-API docs correctly render. We also run a nightly cron job to check the API docs and
translations.
Expand Down Expand Up @@ -260,6 +260,8 @@ Alternatively, you can also regenerate one specific version:

If the version is not for the latest stable minor release series, then add `--historical` to the arguments. For example, use `--historical` if the latest stable release is 0.45.\* but you're generating docs for the patch release 0.44.3.

Additionally, If you are regenerating a dev version, then you can add `--dev` as an argument and the documentation will be built at `/docs/api/<pkg-name>/dev`. For dev versions, end the `--version` in `-dev`, e.g. `-v 1.0.0-dev`. If a release candidate has already been released, use `-v 1.0.0rc1`, for example.

In this case, no commit will be automatically created.

## Generate new API docs
Expand Down Expand Up @@ -287,6 +289,8 @@ This is useful when new docs content is published, usually corresponding to new
11. Run `npm run gen-api -- -p <pkg-name> -v <version>`,
e.g. `npm run gen-api -- -p qiskit -v 0.45.0`

If you are regenerating a dev version, then you can add `--dev` as an argument and the documentation will be built at `/docs/api/<pkg-name>/dev`. For dev versions, end the `--version` in `-dev`, e.g. `-v 1.0.0-dev`. If a release candidate has already been released, use `-v 1.0.0rc1`, for example.

In case you want to save the current version and convert it into a historical one, you can run `npm run make-historical -- -p <pkg-name>` beforehand.

### Generate patch releases
Expand Down
63 changes: 53 additions & 10 deletions scripts/commands/checkLinks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { globby } from "globby";
import yargs from "yargs/yargs";
import { hideBin } from "yargs/helpers";

import { pathExists } from "../lib/fs";
import { File } from "../lib/links/LinkChecker";
import { FileBatch } from "../lib/links/FileBatch";

Expand All @@ -30,6 +31,7 @@ interface Arguments {
[x: string]: unknown;
external: boolean;
currentApis: boolean;
devApis: boolean;
historicalApis: boolean;
qiskitReleaseNotes: boolean;
skipBrokenHistorical: boolean;
Expand All @@ -49,6 +51,11 @@ const readArgs = (): Arguments => {
default: false,
description: "Check the links in the current API docs.",
})
.option("dev-apis", {
type: "boolean",
default: false,
description: "Check the links in the /dev API docs.",
})
.option("historical-apis", {
type: "boolean",
default: false,
Expand Down Expand Up @@ -97,19 +104,28 @@ async function main() {

async function determineFileBatches(args: Arguments): Promise<FileBatch[]> {
const currentBatch = await determineCurrentDocsFileBatch(args);
if (!args.historicalApis) {
return [currentBatch];
const result = [currentBatch];

if (args.devApis) {
const devBatches = await determineDevFileBatches();
result.push(...devBatches);
}

const provider = await determineHistoricalFileBatches("qiskit-ibm-provider");
const runtime = await determineHistoricalFileBatches("qiskit-ibm-runtime", [
"docs/api/qiskit/providers_models.md",
]);
let qiskit: FileBatch[] = [];
if (!args.skipBrokenHistorical) {
qiskit = await determineHistoricalFileBatches("qiskit");
if (args.historicalApis) {
const provider = await determineHistoricalFileBatches(
"qiskit-ibm-provider",
);
const runtime = await determineHistoricalFileBatches("qiskit-ibm-runtime", [
"docs/api/qiskit/providers_models.md",
]);
let qiskit: FileBatch[] = [];
if (!args.skipBrokenHistorical) {
qiskit = await determineHistoricalFileBatches("qiskit");
}
result.push(...provider, ...runtime, ...qiskit);
}
return [currentBatch, ...provider, ...runtime, ...qiskit];

return result;
}

async function determineCurrentDocsFileBatch(
Expand All @@ -121,6 +137,9 @@ async function determineCurrentDocsFileBatch(
// Ignore historical versions
"!docs/api/{qiskit,qiskit-ibm-provider,qiskit-ibm-runtime}/[0-9]*/*",
"!public/api/{qiskit,qiskit-ibm-provider,qiskit-ibm-runtime}/[0-9]*/*",
// Ignore dev version
"!docs/api/{qiskit,qiskit-ibm-provider,qiskit-ibm-runtime}/dev/*",
"!public/api/{qiskit,qiskit-ibm-provider,qiskit-ibm-runtime}/dev/*",
];
const toLoad = [
"docs/api/qiskit/0.44/{algorithms,opflow}.md",
Expand Down Expand Up @@ -157,6 +176,30 @@ async function determineCurrentDocsFileBatch(
return FileBatch.fromGlobs(toCheck, toLoad, description);
}

async function determineDevFileBatches(): Promise<FileBatch[]> {
const devProjects = [];
for (const project of [
"qiskit",
"qiskit-ibm-provider",
"qiskit-ibm-runtime",
]) {
if (await pathExists(`docs/api/${project}/dev`)) {
devProjects.push(project);
}
}

const result = [];
for (const project of devProjects) {
const fileBatch = await FileBatch.fromGlobs(
[`docs/api/${project}/dev/*`, `public/api/${project}/dev/objects.inv`],
[],
`${project} dev docs`,
);
result.push(fileBatch);
}
return result;
}

async function determineHistoricalFileBatches(
projectName: string,
toLoad: string[] = [],
Expand Down
11 changes: 11 additions & 0 deletions scripts/commands/checkPagesRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const PORT = 3000;
interface Arguments {
[x: string]: unknown;
currentApis: boolean;
devApis: boolean;
historicalApis: boolean;
qiskitReleaseNotes: boolean;
translations: boolean;
Expand All @@ -34,6 +35,11 @@ const readArgs = (): Arguments => {
default: false,
description: "Check the pages in the current API docs.",
})
.option("dev-apis", {
type: "boolean",
default: false,
description: "Check the /dev API docs.",
})
.option("historical-apis", {
type: "boolean",
default: false,
Expand Down Expand Up @@ -140,6 +146,11 @@ async function determineFilePaths(args: Arguments): Promise<string[]> {
"!docs/api/{qiskit,qiskit-ibm-provider,qiskit-ibm-runtime}/[0-9]*/*",
);
}
if (!args.devApis) {
globs.push(
"!docs/api/{qiskit,qiskit-ibm-provider,qiskit-ibm-runtime}/dev/*",
);
}
if (!args.qiskitReleaseNotes) {
globs.push("!docs/api/qiskit/release-notes/*");
}
Expand Down
39 changes: 32 additions & 7 deletions scripts/commands/updateApiDocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ interface Arguments {
package: string;
version: string;
historical: boolean;
dev: boolean;
skipDownload: boolean;
}

Expand All @@ -71,6 +72,11 @@ const readArgs = (): Arguments => {
default: false,
description: "Is this a prior release?",
})
.option("dev", {
type: "boolean",
default: false,
description: "Is this a dev release?",
})
.option("skip-download", {
type: "boolean",
default: false,
Expand All @@ -91,7 +97,20 @@ zxMain(async () => {
);
}

const type = args.historical ? "historical" : "latest";
if (args.historical && args.dev) {
throw new Error(
`${args.package} ${args.version} cannot be historical and dev at the same time. Please remove at least only one of these two arguments: --historical, --dev.`,
);
}

const devRegex = /[0-9](rc|-dev)/;
if (args.dev && !args.version.match(devRegex)) {
throw new Error(
`${args.package} ${args.version} is not a correct dev version. Please make sure the version has one of the following suffixes immediately following the patch version: rc, -dev. e.g. 1.0.0rc1 or 1.0.0-dev`,
);
}

const type = args.historical ? "historical" : args.dev ? "dev" : "latest";

const pkg = await Pkg.fromArgs(
args.package,
Expand All @@ -108,7 +127,7 @@ zxMain(async () => {
}

const outputDir = pkg.outputDir(`${getRoot()}/docs`);
if (pkg.isHistorical() && !(await pathExists(outputDir))) {
if (!pkg.isLatest() && !(await pathExists(outputDir))) {
await mkdirp(outputDir);
} else {
console.log(
Expand Down Expand Up @@ -165,7 +184,7 @@ async function convertHtmlToMarkdown(
results.push({ ...result, url });

if (
!pkg.isHistorical() &&
pkg.isLatest() &&
pkg.hasSeparateReleaseNotes &&
file.endsWith("release_notes.html")
) {
Expand Down Expand Up @@ -196,16 +215,22 @@ async function convertHtmlToMarkdown(
for (const result of results) {
let path = urlToPath(result.url);

// Historical versions with a single release notes file should not
// Historical or dev versions with a single release notes file should not
// modify the current API's file.
if (
!pkg.hasSeparateReleaseNotes &&
pkg.isHistorical() &&
!pkg.isLatest() &&
path.endsWith("release-notes.md")
) {
continue;
}

// Dev versions haven't been released yet and we don't want to modify the release notes
// of prior versions
if (pkg.isDev() && path.endsWith("release-notes.md")) {
continue;
}

if (pkg.hasSeparateReleaseNotes && path.endsWith("release-notes.md")) {
// Convert the relative links to absolute links
result.markdown = transformLinks(result.markdown, (link, _) =>
Expand All @@ -230,11 +255,11 @@ async function convertHtmlToMarkdown(

// Add the new release entry to the _toc.json for all historical API versions.
// We don't need to add any entries in projects with a single release notes file.
if (!pkg.isHistorical() && pkg.hasSeparateReleaseNotes) {
if (pkg.isLatest() && pkg.hasSeparateReleaseNotes) {
await updateHistoricalTocFiles(pkg);
}

if (!pkg.isHistorical() && pkg.hasSeparateReleaseNotes) {
if (pkg.isLatest() && pkg.hasSeparateReleaseNotes) {
console.log("Generating release-notes/index");
const markdown = generateReleaseNotesIndex(pkg);
await writeFile(`${markdownPath}/release-notes/index.md`, markdown);
Expand Down
12 changes: 11 additions & 1 deletion scripts/lib/api/Pkg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface ReleaseNoteEntry {
url: string;
}

type PackageType = "latest" | "historical";
type PackageType = "latest" | "historical" | "dev";

/**
* Information about the specific package and version we're dealing with, e.g. qiskit 0.45.
Expand Down Expand Up @@ -149,6 +149,8 @@ export class Pkg {
let path = join(parentDir, "api", this.name);
if (this.isHistorical()) {
path = join(path, this.versionWithoutPatch);
} else if (this.isDev()) {
path = join(path, "dev");
}
return path;
}
Expand All @@ -161,6 +163,14 @@ export class Pkg {
return this.type == "historical";
}

isDev(): boolean {
return this.type == "dev";
}

isLatest(): boolean {
return this.type == "latest";
}

hasObjectsInv(): boolean {
// We don't currently worry about objects.inv for historical API docs because we don't
// expect users to care about it, so we can keep things simple. For example, our copy
Expand Down
6 changes: 5 additions & 1 deletion scripts/lib/api/saveImages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { copyFile } from "fs/promises";

import { Pkg } from "./Pkg";
import { Image } from "./HtmlToMdResult";
import { pathExists } from "../fs";
import { pathExists, rmFilesInFolder } from "../fs";

export async function saveImages(
images: Image[],
Expand All @@ -26,6 +26,10 @@ export async function saveImages(
const destFolder = pkg.outputDir("public/images");
if (!(await pathExists(destFolder))) {
await mkdirp(destFolder);
} else if (pkg.isDev()) {
// We don't want to store images from other versions when we generate a
// different dev version
await rmFilesInFolder(destFolder);
}

await pMap(images, async (img) => {
Expand Down
Loading