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

[rush] Update rush-project.json to follow new proposed schema. #3159

Merged
merged 7 commits into from
Jan 18, 2022
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
431 changes: 146 additions & 285 deletions apps/rush-lib/src/api/RushProjectConfiguration.ts

Large diffs are not rendered by default.

20 changes: 7 additions & 13 deletions apps/rush-lib/src/api/test/RushProjectConfiguration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,23 @@ describe(RushProjectConfiguration.name, () => {
const terminal: Terminal = new Terminal(new StringBufferTerminalProvider());
const rushProjectJson: IRushProjectJson =
await RUSH_PROJECT_CONFIGURATION_FILE.loadConfigurationFileForProjectAsync(terminal, testFolder);
expect(rushProjectJson.projectOutputFolderNames).toMatchInlineSnapshot(`
Array [
"a",
"b",
]
`);
expect(rushProjectJson.phaseOptions?.length).toEqual(2);
expect(rushProjectJson.phaseOptions?.[0].phaseName).toMatchInlineSnapshot(`"_phase:a"`);
expect(rushProjectJson.phaseOptions?.[0].projectOutputFolderNames).toMatchInlineSnapshot(`
expect(rushProjectJson.operationSettings?.length).toEqual(2);
expect(rushProjectJson.operationSettings?.[0].operationName).toMatchInlineSnapshot(`"_phase:a"`);
expect(rushProjectJson.operationSettings?.[0].outputFolderNames).toMatchInlineSnapshot(`
Array [
"a-a",
"a-b",
]
`);
expect(rushProjectJson.phaseOptions?.[1].phaseName).toMatchInlineSnapshot(`"_phase:b"`);
expect(rushProjectJson.phaseOptions?.[1].projectOutputFolderNames).toMatchInlineSnapshot(`
expect(rushProjectJson.operationSettings?.[1].operationName).toMatchInlineSnapshot(`"_phase:b"`);
expect(rushProjectJson.operationSettings?.[1].outputFolderNames).toMatchInlineSnapshot(`
Array [
"b-a",
]
`);
});

it('throws an error when loading a rush-project.json config that lists a phase twice', async () => {
it('throws an error when loading a rush-project.json config that lists an operation twice', async () => {
const testFolder: string = `${__dirname}/jsonFiles/test-project-b`;
const terminal: Terminal = new Terminal(new StringBufferTerminalProvider());
try {
Expand All @@ -44,7 +38,7 @@ describe(RushProjectConfiguration.name, () => {
.replace(/\\/g, '/')
.replace(testFolder.replace(/\\/g, '/'), '<testFolder>');
expect(errorMessage).toMatchInlineSnapshot(
`"The phase \\"_phase:a\\" occurs multiple times in the \\"phaseOptions\\" array in \\"<testFolder>/config/rush-project.json\\"."`
`"The operation \\"_phase:a\\" occurs multiple times in the \\"operationSettings\\" array in \\"<testFolder>/config/rush-project.json\\"."`
);
}
});
Expand Down
12 changes: 5 additions & 7 deletions apps/rush-lib/src/api/test/jsonFiles/rush-project-base.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
{
"projectOutputFolderNames": ["a"],

"phaseOptions": [
"operationSettings": [
{
"phaseName": "_phase:a",
"projectOutputFolderNames": ["a-a"]
"operationName": "_phase:a",
"outputFolderNames": ["a-a"]
},
{
"phaseName": "_phase:b",
"projectOutputFolderNames": ["b-a"]
"operationName": "_phase:b",
"outputFolderNames": ["b-a"]
}
]
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
{
"extends": "../../rush-project-base.json",
"projectOutputFolderNames": ["b"],

"phaseOptions": [
"operationSettings": [
{
"phaseName": "_phase:a",
"projectOutputFolderNames": ["a-b"]
"operationName": "_phase:a",
"outputFolderNames": ["a-b"]
}
]
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
{
"extends": "../../rush-project-base.json",
"projectOutputFolderNames": ["b"],

"phaseOptions": [
"operationSettings": [
{
"phaseName": "_phase:a",
"projectOutputFolderNames": ["a-b"]
"operationName": "_phase:a",
"outputFolderNames": ["a-b"]
},
{
"phaseName": "_phase:a",
"projectOutputFolderNames": ["a-c"]
"operationName": "_phase:a",
"outputFolderNames": ["a-c"]
}
]
}
12 changes: 6 additions & 6 deletions apps/rush-lib/src/logic/taskExecution/ProjectTaskRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { BaseTaskRunner, ITaskRunnerContext } from './BaseTaskRunner';
import { ProjectLogWritable } from './ProjectLogWritable';
import { ProjectBuildCache } from '../buildCache/ProjectBuildCache';
import type { BuildCacheConfiguration } from '../../api/BuildCacheConfiguration';
import { ICacheOptionsForCommand, RushProjectConfiguration } from '../../api/RushProjectConfiguration';
import { IOperationSettings, RushProjectConfiguration } from '../../api/RushProjectConfiguration';
import { CollatedTerminalProvider } from '../../utilities/CollatedTerminalProvider';
import type { CommandLineConfiguration, IPhase } from '../../api/CommandLineConfiguration';
import { RushConstants } from '../RushConstants';
Expand Down Expand Up @@ -413,18 +413,18 @@ export class ProjectTaskRunner extends BaseTaskRunner {
terminal
);
if (projectConfiguration) {
if (projectConfiguration.cacheOptions?.disableBuildCache) {
if (projectConfiguration.disableBuildCacheForProject) {
terminal.writeVerboseLine('Caching has been disabled for this project.');
} else {
const commandOptions: ICacheOptionsForCommand | undefined =
projectConfiguration.cacheOptions.optionsForCommandsByName.get(this._commandName);
if (commandOptions?.disableBuildCache) {
const operationSettings: IOperationSettings | undefined =
projectConfiguration.operationSettingsByOperationName.get(this._commandName);
if (operationSettings?.disableBuildCacheForOperation) {
terminal.writeVerboseLine(
`Caching has been disabled for this project's "${this._commandName}" command.`
);
} else {
const projectOutputFolderNames: ReadonlyArray<string> =
projectConfiguration.projectOutputFolderNamesForPhases.get(this._phase.name) || [];
operationSettings?.outputFolderNames || [];
this._projectBuildCache = await ProjectBuildCache.tryGetProjectBuildCache({
projectConfiguration,
projectOutputFolderNames,
Expand Down
28 changes: 28 additions & 0 deletions apps/rush-lib/src/schemas/anything.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Schema that matches anything",

"oneOf": [
{
"type": "array"
},
{
"type": "boolean"
},
{
"type": "integer"
},
{
"type": "null"
},
{
"type": "number"
},
{
"type": "object"
},
{
"type": "string"
}
]
}
65 changes: 19 additions & 46 deletions apps/rush-lib/src/schemas/rush-project.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "For use with the Rush tool, this file provides per-project configuration options. See http://rushjs.io for details.",

"type": "object",
"additionalProperties": false,
"properties": {
"$schema": {
"description": "Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.",
Expand All @@ -15,45 +16,6 @@
"type": "string"
},

"buildCacheOptions": {
"type": "object",
"properties": {
"disableBuildCache": {
"description": "Selectively disables the build cache for this project. The project will never be restored from cache. This is a useful workaround if that project's build scripts violate the assumptions of the cache, for example by writing files outside the project folder. Where possible, a better solution is to improve the build scripts to be compatible with caching.",
"type": "boolean"
},

"optionsForCommands": {
"description": "Allows for fine-grained control of cache for individual Rush commands.",
"type": "array",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string",
"description": "The Rush command name, as defined in custom-commands.json"
},

"disableBuildCache": {
"description": "Selectively disables the build cache for this come. The project will never be restored from cache. This is a useful workaround if that project's build scripts violate the assumptions of the cache, for example by writing files outside the project folder. Where possible, a better solution is to improve the build scripts to be compatible with caching.",
"type": "boolean"
}
}
}
}
}
},

"projectOutputFolderNames": {
"type": "array",
"description": "Specify the folders where your toolchain writes its output files. If enabled, the Rush build cache will restore these folders from the cache. The strings are folder names under the project root folder. These folders should not be tracked by Git. They must not contain symlinks.",
"items": {
"type": "string"
},
"uniqueItems": true
},

"incrementalBuildIgnoredGlobs": {
"type": "array",
"description": "The incremental analyzer can skip Rush commands for projects whose input files have not changed since the last build. Normally, every Git-tracked file under the project folder is assumed to be an input. Set incrementalBuildIgnoredGlobs to ignore specific files, specified as globs relative to the project folder. The list of file globs will be interpreted the same way your .gitignore file is.",
Expand All @@ -62,25 +24,36 @@
}
},

"phaseOptions": {
"disableBuildCacheForProject": {
"description": "Disable caching for this project. The project will never be restored from cache. This may be useful if this project affects state outside of its folder.",
"type": "boolean"
},

"operationSettings": {
"type": "array",
"description": "Options for individual phases.",
"description": "Options for individual commands and phases.",
"items": {
"type": "object",
"required": ["phaseName"],
"additionalProperties": false,
"required": ["operationName"],
"properties": {
"phaseName": {
"operationName": {
"type": "string",
"description": "The name of the phase. This is the name that appears in command-line.json."
"description": "The name of the operation. This should be a key in the `package.json`'s `scripts` object."
},

"projectOutputFolderNames": {
"outputFolderNames": {
"type": "array",
"description": "Specify the folders where this phase writes its output files. If enabled, the Rush build cache will restore these folders from the cache. The strings are folder names under the project root folder. These folders should not be tracked by Git. They must not contain symlinks.",
"description": "Specify the folders where this operation writes its output files. If enabled, the Rush build cache will restore these folders from the cache. The strings are folder names under the project root folder. These folders should not be tracked by Git. They must not contain symlinks.",
"items": {
"type": "string"
},
"uniqueItems": true
},

"disableBuildCacheForOperation": {
"description": "Disable caching for this operation. The operation will never be restored from cache. This may be useful if this operation affects state outside of its folder.",
"type": "boolean"
}
}
}
Expand Down
69 changes: 69 additions & 0 deletions apps/rush/UPGRADING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Upgrade notes for @microsoft/rush

### Rush 5.60.0

This release of Rush includes a breaking change for the experiment build cache feature. It only affects
monorepos with `buildCacheEnabled=true` in `experiments.json`.

The `<project-root>/config/rush-project.json` file format has changed. The new schema introduces
a concept of "operations" and an `operationSettings` property. An operation
is a command or phase that is invoked in a project. The top-level `projectOutputFolderNames` property
has been removed in favor of a per-operation `outputFolderNames` property. The `phaseOptions` and
`buildCacheOptions` properties have also been removed in favor of a per-operation properties.

Converting to the new format: Although JSON fields have been moved/renamed, their meanings
are essentially the same.

**`rush-project.json`** (OLD)

```js
{
"incrementalBuildIgnoredGlobs": ["temp/**"],
"projectOutputFolderNames": ["output-folder-1", "output-folder-2"],
"phaseOptions": [
{
"phaseName": "_phase:build",
"projectOutputFolderNames": ["output-folder-a", "output-folder-b"]
}
],
"buildCacheOptions": {
"disableBuildCache": false,
"optionsForCommands": [
{
"commandName": "test",
"disableBuildCache": true
}
]
}
}
```

**`rush-project.json`** (NEW)

```js
{
"incrementalBuildIgnoredGlobs": ["temp/**"],

"disableBuildCache": false, // formerly buildCacheOptions.disableBuildCache

"operationSettings": [ // formerly phaseOptions
{
"operationName": "build",

// The "build" operation's output folder names were previously defined
// in the top-level `projectOutputFolderNames` property.
"outputFolderNames": ["output-folder-1", "output-folder-2"]
},
{
"operationName": "_phase:build", // formerly phaseName
"outputFolderNames": ["output-folder-a", "output-folder-b"]
},
{
"operationName": "test",
"disableBuildCacheForOperation": true
}
]
}
```
iclanton marked this conversation as resolved.
Show resolved Hide resolved

For details see [issue #2300](https://github.com/microsoft/rushstack/issues/2300#issuecomment-1012622369).
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@microsoft/rush",
"comment": "(BREAKING CHANGE) Some experimental fields have been renamed in \"config/rush-project.json\". Please see UPGRADING.md for details.",
"type": "none"
}
],
"packageName": "@microsoft/rush"
}
15 changes: 8 additions & 7 deletions common/config/azure-pipelines/templates/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ steps:
displayName: 'Rush Rebuild (install-run-rush)'
env:
# Prevent time-based browserslist update warning
# See https://github.com/microsoft/rushstack/issues/2981
BROWSERSLIST_IGNORE_OLD_DATA: 1
- script: 'node apps/rush-lib/lib/start.js build --verbose --production'
displayName: 'Rush Build (rush-lib)'
env:
# Prevent time-based browserslist update warning
# See https://github.com/microsoft/rushstack/issues/2981
# See https://github.com/microsoft/rushstack/issues/2981
BROWSERSLIST_IGNORE_OLD_DATA: 1
# Re-enable after the schema changes to rush-project.json are published and pulled in
# - script: 'node apps/rush-lib/lib/start.js build --verbose --production'
# displayName: 'Rush Build (rush-lib)'
# env:
# # Prevent time-based browserslist update warning
# # See https://github.com/microsoft/rushstack/issues/2981
# BROWSERSLIST_IGNORE_OLD_DATA: 1
- script: 'node repo-scripts/repo-toolbox/lib/start.js readme --verify'
displayName: 'Ensure repo README is up-to-date'