Skip to content
Open
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
9 changes: 9 additions & 0 deletions docs/manifest-releaser.md
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,15 @@ workspace, and updates any packages that were directly bumped by release-please,
or that should be patch-bumped because one of their transitive dependencies was
bumped. The cargo lockfile is also updated.

A workspace member whose manifest sets `publish = false` is still bumped so that
its own dependents stay consistent, but it does not get a release of its own: no
release pull request, tag, or `.release-please-manifest.json` entry is created
for it when it is pulled in only as a dependent. A `publish = false` crate that
is listed in your release-please config and has changes of its own is released
as usual (its version is tracked and tagged); `publish = false` only suppresses
the release of a crate that would otherwise be released solely because a
dependency was bumped.

Note: when the Rust releaser is used standalone (with the `release-pr` /
`github-release` commands), it also tries to update monorepo dependencies, but
it doesn't build a crate graph. When the Rust releaser is used in conjunction
Expand Down
10 changes: 10 additions & 0 deletions src/plugins/cargo-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ interface CrateInfo {
* Parsed cargo manifest
*/
manifest: CargoManifest;

/**
* `false` when the manifest sets `publish = false`.
*/
publishable: boolean;
}

/**
Expand Down Expand Up @@ -163,6 +168,7 @@ export class CargoWorkspace extends WorkspacePlugin<CrateInfo> {
manifest,
manifestContent: manifestContent.parsedContent,
manifestPath,
publishable: manifest.package?.publish !== false,
});
}
return {
Expand Down Expand Up @@ -394,6 +400,10 @@ export class CargoWorkspace extends WorkspacePlugin<CrateInfo> {
return candidate.config.releaseType === 'rust';
}

protected shouldCreateReleasePullRequest(pkg: CrateInfo): boolean {
return pkg.publishable;
}

protected packageNameFromPackage(pkg: CrateInfo): string {
return pkg.name;
}
Expand Down
22 changes: 21 additions & 1 deletion src/plugins/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ export abstract class WorkspacePlugin<T> extends ManifestPlugin {
newCandidatePaths.add(newCandidate.path);
newCandidates.push(newCandidate);
}
} else if (!this.shouldCreateReleasePullRequest(pkg)) {
// Dependent-only bump: its version is already in `updatedVersions`, so
// dependents are still updated, but it opts out of its own release.
this.logger.info(
`Skipping release pull request for ${this.packageNameFromPackage(
pkg
)}`
);
} else {
// otherwise, build a new pull request with changelog and entry update
this.logger.info(
Expand Down Expand Up @@ -266,7 +274,10 @@ export abstract class WorkspacePlugin<T> extends ManifestPlugin {
const version = this.bumpVersion(pkg);
this.logger.debug(`version: ${version} forced bump`);
updatedVersions.set(packageName, version);
if (this.isReleaseVersion(version)) {
if (
this.isReleaseVersion(version) &&
this.shouldCreateReleasePullRequest(pkg)
) {
updatedPathVersions.set(this.pathFromPackage(pkg), version);
}
}
Expand All @@ -286,6 +297,15 @@ export abstract class WorkspacePlugin<T> extends ManifestPlugin {
return true;
}

/**
* Whether a dependent-only package should get its own release pull request.
* Defaults to `true`; the package is version-bumped regardless.
* @param {T} _pkg The dependent package being considered
*/
protected shouldCreateReleasePullRequest(_pkg: T): boolean {
return true;
}

/**
* Given a package, return the new bumped version after updating
* the dependency.
Expand Down
3 changes: 3 additions & 0 deletions src/updaters/rust/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ export interface CargoWorkspace {
export interface CargoPackage {
name?: string;
version?: string;
// `publish = false` (or an allow-list of registries). When `false`, the
// crate is a workspace member that is never published to a registry.
publish?: boolean | string[];
}

export interface CargoDependencies {
Expand Down

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[workspace]
members = ["packages/rustA", "packages/rustUnpub"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "pkgA"
version = "1.1.1"

[dependencies]
tracing = "1.0.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "pkgUnpub"
version = "6.6.6"
publish = false

[dependencies]
pkgA = { version = "1.1.1", path = "../pkgA" }
tracing = "1.0.0"
53 changes: 53 additions & 0 deletions test/plugins/cargo-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,59 @@ describe('CargoWorkspace plugin', () => {
assertHasUpdate(updates, 'packages/rustE/Cargo.toml', RawContent);
snapshot(dateSafe(rustCandidate!.pullRequest.body.toString()));
});
it('does not open a release pull request for a publish = false dependent', async () => {
const publishFalsePath =
'./test/fixtures/plugins/cargo-workspace-publish-false';
// Only pkgA has a release candidate; pkgUnpub (publish = false) depends
// on it and is pulled into the graph only as a dependent.
const candidates: CandidateReleasePullRequest[] = [
buildMockCandidatePullRequest('packages/rustA', 'rust', '1.1.2', {
component: 'pkgA',
updates: [
buildMockPackageUpdate(
'packages/rustA/Cargo.toml',
'packages/rustA/Cargo.toml'
),
],
}),
];
stubFilesFromFixtures({
sandbox,
github,
fixturePath: publishFalsePath,
files: [
'Cargo.toml',
'packages/rustA/Cargo.toml',
'packages/rustUnpub/Cargo.toml',
],
flatten: false,
targetBranch: 'main',
});
sandbox
.stub(github, 'findFilesByGlobAndRef')
.withArgs('packages/rustA', 'main')
.resolves(['packages/rustA'])
.withArgs('packages/rustUnpub', 'main')
.resolves(['packages/rustUnpub']);
plugin = new CargoWorkspace(
github,
'main',
{
'packages/rustA': {
releaseType: 'rust',
},
},
{
merge: false,
}
);
const newCandidates = await plugin.run(candidates);
// Only pkgA is released — no standalone candidate for the publish = false
// crate.
expect(newCandidates).lengthOf(1);
expect(newCandidates.find(c => c.path === 'packages/rustUnpub')).to.be
.undefined;
});
it('can skip merging rust packages', async () => {
// This is the same setup as 'walks dependency tree and updates previously untouched packages'
const candidates: CandidateReleasePullRequest[] = [
Expand Down
Loading