Skip to content

Allow users to omit packages #98

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

Merged
merged 1 commit into from
Oct 25, 2023
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
110 changes: 0 additions & 110 deletions src/functional.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,116 +606,6 @@ describe('create-release-branch (functional)', () => {
);
});

it('errors before making any changes if the edited release spec omits changed packages', async () => {
await withMonorepoProjectEnvironment(
{
packages: {
$root$: {
name: '@scope/monorepo',
version: '1.0.0',
directoryPath: '.',
},
a: {
name: '@scope/a',
version: '0.1.2',
directoryPath: 'packages/a',
},
b: {
name: '@scope/b',
version: '1.1.4',
directoryPath: 'packages/b',
},
c: {
name: '@scope/c',
version: '2.0.13',
directoryPath: 'packages/c',
},
d: {
name: '@scope/d',
version: '1.2.3',
directoryPath: 'packages/d',
},
},
workspaces: {
'.': ['packages/*'],
},
},
async (environment) => {
await expect(
environment.runTool({
releaseSpecification: {
packages: {
a: 'major',
c: 'patch',
},
},
}),
).toThrowExecaError(
`
Error: Your release spec could not be processed due to the following issues:

* The following packages, which have changed since their latest release, are missing.

- @scope/b
- @scope/d

Consider including them in the release spec so that any packages that rely on them won't break in production.

If you are ABSOLUTELY SURE that this won't occur, however, and want to postpone the release of a package, then list it with a directive of "intentionally-skip". For example:

packages:
"@scope/b": intentionally-skip
"@scope/d": intentionally-skip

The release spec file has been retained for you to edit again and make the necessary fixes. Once you've done this, re-run this tool.

<<release-spec-file-path>>
<<stack-trace>>
`.trim(),
{
replacements: [
{
from: `${environment.tempDirectoryPath}/RELEASE_SPEC.yml`,
to: '<<release-spec-file-path>>',
},
],
},
);

expect(await environment.readJsonFile('package.json')).toStrictEqual({
name: '@scope/monorepo',
version: '1.0.0',
private: true,
workspaces: ['packages/*'],
});
expect(
await environment.readJsonFileWithinPackage('a', 'package.json'),
).toStrictEqual({
name: '@scope/a',
version: '0.1.2',
});
expect(
await environment.readJsonFileWithinPackage('b', 'package.json'),
).toStrictEqual({
name: '@scope/b',
version: '1.1.4',
});
expect(
await environment.readJsonFileWithinPackage('c', 'package.json'),
).toStrictEqual({
name: '@scope/c',
version: '2.0.13',
});
expect(
await environment.readJsonFileWithinPackage('d', 'package.json'),
).toStrictEqual({
name: '@scope/d',
version: '1.2.3',
});
},
);
});

it('does not update the versions of any packages that have been tagged with intentionally-skip', async () => {
await withMonorepoProjectEnvironment(
{
Expand Down
112 changes: 0 additions & 112 deletions src/release-specification.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -572,118 +572,6 @@ Your release spec could not be processed due to the following issues:
});
});

it('throws if there are any packages not listed in the release spec which have changed', async () => {
await withSandbox(async (sandbox) => {
const project = buildMockProject({
workspacePackages: {
a: buildMockPackage('a', {
hasChangesSinceLatestRelease: true,
}),
b: buildMockPackage('b', {
hasChangesSinceLatestRelease: true,
}),
c: buildMockPackage('c', {
hasChangesSinceLatestRelease: true,
}),
},
});
const releaseSpecificationPath = path.join(
sandbox.directoryPath,
'release-spec',
);
await fs.promises.writeFile(
releaseSpecificationPath,
YAML.stringify({
packages: {
a: 'major',
},
}),
);

await expect(
validateReleaseSpecification(project, releaseSpecificationPath),
).rejects.toThrow(
`
Your release spec could not be processed due to the following issues:

* The following packages, which have changed since their latest release, are missing.

- b
- c

Consider including them in the release spec so that any packages that rely on them won't break in production.

If you are ABSOLUTELY SURE that this won't occur, however, and want to postpone the release of a package, then list it with a directive of "intentionally-skip". For example:

packages:
b: intentionally-skip
c: intentionally-skip

The release spec file has been retained for you to edit again and make the necessary fixes. Once you've done this, re-run this tool.

${releaseSpecificationPath}
`.trim(),
);
});
});

it('throws if there are any packages listed in the release spec which have changed but their version specifiers are null', async () => {
await withSandbox(async (sandbox) => {
const project = buildMockProject({
workspacePackages: {
a: buildMockPackage('a', {
hasChangesSinceLatestRelease: true,
}),
b: buildMockPackage('b', {
hasChangesSinceLatestRelease: true,
}),
c: buildMockPackage('c', {
hasChangesSinceLatestRelease: true,
}),
},
});
const releaseSpecificationPath = path.join(
sandbox.directoryPath,
'release-spec',
);
await fs.promises.writeFile(
releaseSpecificationPath,
YAML.stringify({
packages: {
a: 'major',
b: null,
c: null,
},
}),
);

await expect(
validateReleaseSpecification(project, releaseSpecificationPath),
).rejects.toThrow(
`
Your release spec could not be processed due to the following issues:

* The following packages, which have changed since their latest release, are missing.

- b
- c

Consider including them in the release spec so that any packages that rely on them won't break in production.

If you are ABSOLUTELY SURE that this won't occur, however, and want to postpone the release of a package, then list it with a directive of "intentionally-skip". For example:

packages:
b: intentionally-skip
c: intentionally-skip

The release spec file has been retained for you to edit again and make the necessary fixes. Once you've done this, re-run this tool.

${releaseSpecificationPath}
`.trim(),
);
});
});

it('throws if there are any packages in the release with a major version bump using the word "major", but any of their dependents defined as "dependencies" are not listed in the release', async () => {
await withSandbox(async (sandbox) => {
const project = buildMockProject({
Expand Down
78 changes: 0 additions & 78 deletions src/release-specification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,84 +207,6 @@ export async function validateReleaseSpecification(

const errors: { message: string | string[]; lineNumber?: number }[] = [];

const changedPackageNames = Object.keys(project.workspacePackages).filter(
(packageName) =>
project.workspacePackages[packageName].hasChangesSinceLatestRelease,
);

const missingChangedPackageNames = changedPackageNames.filter(
(packageName) =>
!hasProperty(unvalidatedReleaseSpecification.packages, packageName) ||
unvalidatedReleaseSpecification.packages[packageName] === null,
);

const packageNamesToReportMissing = missingChangedPackageNames.filter(
(missingChangedPackageName) => {
const missingChangedPackage =
project.workspacePackages[missingChangedPackageName];

const isInternalDependency = Object.values(
project.workspacePackages,
).some((workspacePackage) => {
const { dependencies, peerDependencies } =
workspacePackage.validatedManifest;
return (
hasProperty(dependencies, missingChangedPackageName) ||
hasProperty(peerDependencies, missingChangedPackageName)
);
});

const hasInternalDependencyWithBreakingChanges = Object.keys({
...missingChangedPackage.validatedManifest.dependencies,
...missingChangedPackage.validatedManifest.peerDependencies,
})
.filter((dependency) => project.workspacePackages[dependency])
.some((dependency) => {
const internalDependencyVersionSpecifierOrDirective =
unvalidatedReleaseSpecification.packages[dependency];
return (
internalDependencyVersionSpecifierOrDirective &&
(internalDependencyVersionSpecifierOrDirective === 'major' ||
(isValidSemver(internalDependencyVersionSpecifierOrDirective) &&
diff(
missingChangedPackage.validatedManifest.version,
internalDependencyVersionSpecifierOrDirective,
) === 'major'))
);
});

return !isInternalDependency && !hasInternalDependencyWithBreakingChanges;
},
);

if (packageNamesToReportMissing.length > 0) {
errors.push({
message: [
'The following packages, which have changed since their latest release, are missing.',
packageNamesToReportMissing
.map((packageName) => ` - ${packageName}`)
.join('\n'),
" Consider including them in the release spec so that any packages that rely on them won't break in production.",
` If you are ABSOLUTELY SURE that this won't occur, however, and want to postpone the release of a package, then list it with a directive of "intentionally-skip". For example:`,
YAML.stringify({
packages: packageNamesToReportMissing.reduce(
(object, packageName) => {
return {
...object,
[packageName]: INTENTIONALLY_SKIP_PACKAGE_DIRECTIVE,
};
},
{},
),
})
.trim()
.split('\n')
.map((line) => ` ${line}`)
.join('\n'),
].join('\n\n'),
});
}

Object.entries(unvalidatedReleaseSpecification.packages).forEach(
([changedPackageName, versionSpecifierOrDirective], index) => {
const lineNumber = indexOfFirstUsableLine + index + 2;
Expand Down