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

refactor(release:report): Split release report commands #12850

Merged
merged 24 commits into from
Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from 21 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: 1 addition & 1 deletion build-tools/packages/build-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $ npm install -g @fluid-tools/build-cli
$ flub COMMAND
running command...
$ flub (--version|-V)
@fluid-tools/build-cli/0.5.0
@fluid-tools/build-cli/0.6.0
$ flub --help [COMMAND]
USAGE
$ flub COMMAND
Expand Down
105 changes: 75 additions & 30 deletions build-tools/packages/build-cli/docs/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
Release commands are used to manage the Fluid release process.

* [`flub release`](#flub-release)
* [`flub release history`](#flub-release-history)
* [`flub release report`](#flub-release-report)

## `flub release`
Expand Down Expand Up @@ -46,61 +47,105 @@ DESCRIPTION

_See code: [src/commands/release.ts](https://github.com/microsoft/FluidFramework/blob/main/build-tools/packages/build-cli/src/commands/release.ts)_

## `flub release report`
## `flub release history`

Generates a report of Fluid Framework releases.
Prints a list of released versions of a package or release group. Releases are gathered from the git tags in repo containing the working directory.

```
USAGE
$ flub release report [--json] [--days <value>] [-s | -r] [-g client|server|azure|build-tools [--all | -o
<value>]] [-p <value> ] [--limit <value> ] [-v]
$ flub release history [-g client|server|azure|build-tools | -p <value>] [-l <value>] [-v]

FLAGS
-g, --releaseGroup=<option> Name of the release group
<options: client|server|azure|build-tools>
-o, --output=<value> Output JSON report files to this location.
-l, --limit=<value> Limits the number of displayed releases for each release group. Results are sorted by
semver, so '--limit 10' will return the 10 highest semver releases for the release group.
-p, --package=<value> Name of package.
-r, --mostRecent Always pick the most recent version as the latest (ignore semver version sorting).
-s, --highest Always pick the greatest semver version as the latest (ignore dates).
-v, --verbose Verbose logging.
--all List all releases. Useful when you want to see all the releases done for a release group
or package. The number of results can be limited using the --limit argument.
--days=<value> [default: 10] The number of days to look back for releases to report.
--limit=<value> Limits the number of displayed releases for each release group.

DESCRIPTION
Prints a list of released versions of a package or release group. Releases are gathered from the git tags in repo
containing the working directory.

Use 'npm view' to list published packages based on the public npm registry.

The number of results can be limited using the --limit argument.

EXAMPLES
List all the releases of the azure release group.

$ flub release history -g azure

List the 10 most recent client releases.

$ flub release history -g client --limit 10
```

## `flub release report`

Generates a report of Fluid Framework releases.

```
USAGE
$ flub release report [--json] [-i | -r | -s] [-g client|server|azure|build-tools] [-o <value>] [-v]

FLAGS
-g, --releaseGroup=<option>
Report only on this release group. If also pass --interactive, --highest, or --mostRecent, then the report will only
include this release group at the selected version.

If you pass this flag by itself, the command will use the version of the release group at the current commit in the
repo, but will also include its direct Fluid dependencies.

If you want to report on a particular release, check out the git tag for the release version you want to report on
before running this command.
<options: client|server|azure|build-tools>

-i, --interactive
Choose the version of each release group and package to contain in the release report.

-o, --output=<value>
Output JSON report files to this directory.

-r, --mostRecent
Always pick the most recent version as the latest (ignore semver version sorting).

-s, --highest
Always pick the greatest semver version as the latest (ignore dates).

-v, --verbose
Verbose logging.

GLOBAL FLAGS
--json Format output as json.

DESCRIPTION
Generates a report of Fluid Framework releases.

The release report command is used to produce a report of all the packages that were released and their current
version. After a release, it is useful to generate this report to provide to customers, so they can update their
dependencies to the most recent version.
The release report command is used to produce a report of all the packages that were released and their version. After
a release, it is useful to generate this report to provide to customers, so they can update their dependencies to the
most recent version.

The command will prompt you to select versions for a package or release group in the event that multiple versions have
recently been released.
The command operates in two modes: "whole repo" or "release group." The default mode is "whole repo." In this mode,
the command will look at the git tags in the repo to determine the versions, and will include all release groups and
packages in the repo. You can control which version of each package and release group is included in the report using
the --interactive, --mostRecent, and --highest flags.

Using the --all flag, you can list all the releases for a given release group or package.
The "release group" mode can be activated by passing a --releaseGroup flag. In this mode, the specified release
group's version will be loaded from the repo, and its immediate Fluid dependencies will be included in the report.
This is useful when we want to include only the dependency versions that the release group depends on in the report.

EXAMPLES
Output all release report files to the current directory.

$ flub release report -o .

Generate a minimal release report and display it in the terminal.
Generate a release report of the highest semver release for each package and release group and display it in the
terminal only.

$ flub release report

Generate a minimal release report and output it to stdout as JSON.

$ flub release report --json

List all the releases of the azure release group.
Output all release report files to the current directory.

$ flub release report --all -g azure
$ flub release report -o .

List the 10 most recent client releases.
Generate a release report for each package and release group in the repo interactively.

$ flub release report --all -g client --limit 10
$ flub release report -i
```
15 changes: 14 additions & 1 deletion build-tools/packages/build-cli/src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,21 @@ export abstract class BaseCommand<T extends typeof BaseCommand.flags>
private _context: Context | undefined;
private _logger: CommandLogger | undefined;

/**
* Parses the command arguments and stores them in parsedOutput.
*
* @remarks
*
* This function does nothing if parsedOutput is already defined.
*/
protected async parseCmdArgs() {
if (this.parsedOutput === undefined) {
this.parsedOutput = await this.parse(this.ctor);
}
}

async init() {
this.parsedOutput = await this.parse(this.ctor);
await this.parseCmdArgs();
}

async catch(err: any) {
Expand Down
156 changes: 156 additions & 0 deletions build-tools/packages/build-cli/src/commands/release/history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*!
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
* Licensed under the MIT License.
*/
import { Flags } from "@oclif/core";
import chalk from "chalk";
import { table } from "table";

import { detectBumpType } from "@fluid-tools/version-tools";

import { packageSelectorFlag, releaseGroupFlag } from "../../flags";
import {
ReleaseReport,
VersionDetails,
getDisplayDate,
getDisplayDateRelative,
sortVersions,
} from "../../lib";
import { ReleaseGroup, ReleasePackage } from "../../releaseGroups";
import { ReleaseReportBaseCommand, ReleaseSelectionMode } from "./report";

const DEFAULT_MIN_VERSION = "0.0.0";

/**
* Prints a list of released versions of a package or release group. Releases are gathered from the git tags in repo
* containing the working directory.
*
* @remarks
* Use 'npm view' to list published packages based on the public npm registry.
*
* The number of results can be limited using the --limit argument.
*/
export default class ReleaseHistoryCommand<
T extends typeof ReleaseHistoryCommand.flags,
> extends ReleaseReportBaseCommand<T> {
static description = `Prints a list of released versions of a package or release group. Releases are gathered from the git tags in repo containing the working directory.

Use 'npm view' to list published packages based on the public npm registry.

The number of results can be limited using the --limit argument.`;

static examples = [
{
description: "List all the releases of the azure release group.",
command: "<%= config.bin %> <%= command.id %> -g azure",
},
{
description: "List the 10 most recent client releases.",
command: "<%= config.bin %> <%= command.id %> -g client --limit 10",
},
];

static flags = {
releaseGroup: releaseGroupFlag({
required: false,
exclusive: ["package"],
}),
package: packageSelectorFlag({
required: false,
exclusive: ["releaseGroup"],
}),
limit: Flags.integer({
char: "l",
description: `Limits the number of displayed releases for each release group. Results are sorted by semver, so '--limit 10' will return the 10 highest semver releases for the release group.`,
}),
...ReleaseReportBaseCommand.flags,
};

static enableJsonFlag = true;

defaultMode: ReleaseSelectionMode = "date";
releaseGroupOrPackage: ReleaseGroup | ReleasePackage | undefined;

public async run(): Promise<{ reports: ReleaseReport[] }> {
this.releaseGroupOrPackage =
this.processedFlags.releaseGroup ?? this.processedFlags.package;

const context = await this.getContext();
this.releaseData = await this.collectReleaseData(
context,
this.defaultMode,
this.releaseGroupOrPackage,
false,
);
if (this.releaseData === undefined) {
tylerbutler marked this conversation as resolved.
Show resolved Hide resolved
this.error(`No releases found for ${this.releaseGroupOrPackage}`);
}

const reports: ReleaseReport[] = [];

for (const [pkgOrReleaseGroup, data] of Object.entries(this.releaseData)) {
const versions = sortVersions([...data.versions], "version");
const releaseTable = this.generateAllReleasesTable(pkgOrReleaseGroup, versions);

this.log(
table(releaseTable, {
singleLine: true,
}),
);
}

// When the --json flag is passed, the command will return the raw data as JSON.
return { reports };
}

/**
* Generates table data for all versions of a package/release group.
*/
private generateAllReleasesTable(
pkgOrReleaseGroup: ReleasePackage | ReleaseGroup,
versions: VersionDetails[],
): string[][] {
const tableData: string[][] = [];
const releases = sortVersions(versions, "version").reverse();

let index = 0;
for (const ver of releases) {
const displayPreviousVersion =
index >= 1 ? releases[index - 1].version : DEFAULT_MIN_VERSION;

const displayDate = getDisplayDate(ver.date);
const highlight = this.isRecentReleaseByDate(ver.date) ? chalk.green : chalk.white;
const displayRelDate = highlight(getDisplayDateRelative(ver.date));

const bumpType = detectBumpType(displayPreviousVersion, ver.version);
const displayBumpType = highlight(`${bumpType}`);

const displayVersionSection = chalk.grey(
`${highlight(ver.version)} <-- ${displayPreviousVersion}`,
);

tableData.push([
pkgOrReleaseGroup,
displayBumpType,
displayRelDate,
displayDate,
displayVersionSection,
]);

index++;
}

const limit = this.processedFlags.limit;
if (limit !== undefined && tableData.length > limit) {
tylerbutler marked this conversation as resolved.
Show resolved Hide resolved
this.info(
`Reached the release limit (${limit}), ignoring the remaining ${
tableData.length - limit
} releases.`,
);
// The most recent releases are last, so slice from the end.
return tableData.slice(-limit);
}

return tableData;
}
}
Loading