Skip to content

Commit b12904a

Browse files
authored
feat: add support for bazel (#2239)
1 parent 3569f15 commit b12904a

File tree

12 files changed

+390
-20
lines changed

12 files changed

+390
-20
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ Release Please automates releases for the following flavors of repositories:
182182

183183
| release type | description |
184184
|---------------------|---------------------------------------------------------|
185+
| `bazel` | [A Bazel module, with a MODULE.bazel and a CHANGELOG.md](https://bazel.build/external/module) |
185186
| `dart` | A repository with a pubspec.yaml and a CHANGELOG.md |
186187
| `elixir` | A repository with a mix.exs and a CHANGELOG.md |
187188
| `go` | A repository with a CHANGELOG.md |

__snapshots__/cli.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ Options:
4040
[string]
4141
--release-type what type of repo is a release being created
4242
for?
43-
[choices: "dart", "dotnet-yoshi", "elixir", "expo", "go", "go-yoshi", "helm",
44-
"java", "java-backport", "java-bom", "java-lts", "java-yoshi",
43+
[choices: "bazel", "dart", "dotnet-yoshi", "elixir", "expo", "go", "go-yoshi",
44+
"helm", "java", "java-backport", "java-bom", "java-lts", "java-yoshi",
4545
"java-yoshi-mono-repo", "krm-blueprint", "maven", "node", "ocaml", "php",
4646
"php-yoshi", "python", "ruby", "ruby-yoshi", "rust", "salesforce", "sfdx",
4747
"simple", "terraform-module"]
@@ -241,8 +241,8 @@ Options:
241241
[string]
242242
--release-type what type of repo is a release being created
243243
for?
244-
[choices: "dart", "dotnet-yoshi", "elixir", "expo", "go", "go-yoshi", "helm",
245-
"java", "java-backport", "java-bom", "java-lts", "java-yoshi",
244+
[choices: "bazel", "dart", "dotnet-yoshi", "elixir", "expo", "go", "go-yoshi",
245+
"helm", "java", "java-backport", "java-bom", "java-lts", "java-yoshi",
246246
"java-yoshi-mono-repo", "krm-blueprint", "maven", "node", "ocaml", "php",
247247
"php-yoshi", "python", "ruby", "ruby-yoshi", "rust", "salesforce", "sfdx",
248248
"simple", "terraform-module"]

__snapshots__/module-bazel.js

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
exports['ModuleBazel updateContent updates version in MODULE.bazel file 1'] = `
2+
module(
3+
name = "rules_cc",
4+
version = "0.0.5",
5+
compatibility_level = 1,
6+
)
7+
8+
bazel_dep(name = "bazel_skylib", version = "1.3.0")
9+
bazel_dep(name = "platforms", version = "0.0.7")
10+
11+
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
12+
use_repo(cc_configure, "local_config_cc_toolchains")
13+
14+
register_toolchains("@local_config_cc_toolchains//:all")
15+
16+
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
17+
`
18+
19+
exports['ModuleBazel updateContent updates version when inline 1'] = `
20+
module(name = "rules_cc", version = "0.0.5")
21+
22+
bazel_dep(name = "bazel_skylib", version = "1.3.0")
23+
bazel_dep(name = "platforms", version = "0.0.7")
24+
25+
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
26+
use_repo(cc_configure, "local_config_cc_toolchains")
27+
28+
register_toolchains("@local_config_cc_toolchains//:all")
29+
30+
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
31+
`
32+
33+
exports['ModuleBazel updateContent updates version when ordered improperly 1'] = `
34+
bazel_dep(name = "bazel_skylib", version = "1.3.0")
35+
bazel_dep(name = "platforms", version = "0.0.7")
36+
37+
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
38+
use_repo(cc_configure, "local_config_cc_toolchains")
39+
40+
module(name = "rules_cc", version = "0.0.5")
41+
42+
register_toolchains("@local_config_cc_toolchains//:all")
43+
44+
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
45+
`

src/factory.ts

+18-16
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,26 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import {Strategy} from './strategy';
15+
import {ConfigurationError} from './errors';
16+
import {buildChangelogNotes} from './factories/changelog-notes-factory';
17+
import {buildVersioningStrategy} from './factories/versioning-strategy-factory';
18+
import {GitHub} from './github';
19+
import {ReleaserConfig} from './manifest';
20+
import {BaseStrategyOptions} from './strategies/base';
21+
import {Bazel} from './strategies/bazel';
22+
import {Dart} from './strategies/dart';
23+
import {DotnetYoshi} from './strategies/dotnet-yoshi';
24+
import {Elixir} from './strategies/elixir';
25+
import {Expo} from './strategies/expo';
1626
import {Go} from './strategies/go';
1727
import {GoYoshi} from './strategies/go-yoshi';
28+
import {Helm} from './strategies/helm';
29+
import {Java} from './strategies/java';
1830
import {JavaYoshi} from './strategies/java-yoshi';
1931
import {JavaYoshiMonoRepo} from './strategies/java-yoshi-mono-repo';
2032
import {KRMBlueprint} from './strategies/krm-blueprint';
33+
import {Maven} from './strategies/maven';
34+
import {Node} from './strategies/node';
2135
import {OCaml} from './strategies/ocaml';
2236
import {PHP} from './strategies/php';
2337
import {PHPYoshi} from './strategies/php-yoshi';
@@ -28,23 +42,10 @@ import {Rust} from './strategies/rust';
2842
import {Sfdx} from './strategies/sfdx';
2943
import {Simple} from './strategies/simple';
3044
import {TerraformModule} from './strategies/terraform-module';
31-
import {Helm} from './strategies/helm';
32-
import {Elixir} from './strategies/elixir';
33-
import {Dart} from './strategies/dart';
34-
import {Node} from './strategies/node';
35-
import {Expo} from './strategies/expo';
36-
import {GitHub} from './github';
37-
import {ReleaserConfig} from './manifest';
45+
import {Strategy} from './strategy';
3846
import {AlwaysBumpPatch} from './versioning-strategies/always-bump-patch';
39-
import {ServicePackVersioningStrategy} from './versioning-strategies/service-pack';
4047
import {DependencyManifest} from './versioning-strategies/dependency-manifest';
41-
import {BaseStrategyOptions} from './strategies/base';
42-
import {DotnetYoshi} from './strategies/dotnet-yoshi';
43-
import {Java} from './strategies/java';
44-
import {Maven} from './strategies/maven';
45-
import {buildVersioningStrategy} from './factories/versioning-strategy-factory';
46-
import {buildChangelogNotes} from './factories/changelog-notes-factory';
47-
import {ConfigurationError} from './errors';
48+
import {ServicePackVersioningStrategy} from './versioning-strategies/service-pack';
4849

4950
export * from './factories/changelog-notes-factory';
5051
export * from './factories/plugin-factory';
@@ -107,6 +108,7 @@ const releasers: Record<string, ReleaseBuilder> = {
107108
helm: options => new Helm(options),
108109
elixir: options => new Elixir(options),
109110
dart: options => new Dart(options),
111+
bazel: options => new Bazel(options),
110112
};
111113

112114
export async function buildStrategy(

src/strategies/bazel.ts

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import {Update} from '../update';
16+
import {ModuleBazel} from '../updaters/bazel/module-bazel';
17+
import {Changelog} from '../updaters/changelog';
18+
import {BaseStrategy, BaseStrategyOptions, BuildUpdatesOptions} from './base';
19+
20+
export class Bazel extends BaseStrategy {
21+
readonly versionFile: string;
22+
constructor(options: BaseStrategyOptions) {
23+
super(options);
24+
this.versionFile = options.versionFile ?? 'MODULE.bazel';
25+
}
26+
protected async buildUpdates(
27+
options: BuildUpdatesOptions
28+
): Promise<Update[]> {
29+
const updates: Update[] = [];
30+
const version = options.newVersion;
31+
32+
updates.push({
33+
path: this.addPath(this.changelogPath),
34+
createIfMissing: true,
35+
updater: new Changelog({
36+
version,
37+
changelogEntry: options.changelogEntry,
38+
}),
39+
});
40+
41+
updates.push({
42+
path: this.addPath(this.versionFile),
43+
createIfMissing: false,
44+
updater: new ModuleBazel({
45+
version,
46+
}),
47+
});
48+
49+
return updates;
50+
}
51+
}

src/updaters/bazel/module-bazel.ts

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import {DefaultUpdater} from '../default';
16+
17+
/**
18+
* Updates a Bazel Module file.
19+
*/
20+
export class ModuleBazel extends DefaultUpdater {
21+
updateContent(content: string): string {
22+
const match = content.match(
23+
/module[\s\S]*?\([\s\S]*?version\s*=\s*(['"])(.*?)\1/m
24+
);
25+
if (!match) {
26+
return content;
27+
}
28+
const [fullMatch, , version] = match;
29+
const module = fullMatch.replace(version, this.version.toString());
30+
return content.replace(fullMatch, module);
31+
}
32+
}

test/strategies/bazel.ts

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Copyright 2024 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import {expect} from 'chai';
16+
import {afterEach, beforeEach, describe, it} from 'mocha';
17+
import * as sinon from 'sinon';
18+
import {GitHub} from '../../src/github';
19+
import {Bazel} from '../../src/strategies/bazel';
20+
import {ModuleBazel} from '../../src/updaters/bazel/module-bazel';
21+
import {Changelog} from '../../src/updaters/changelog';
22+
import {TagName} from '../../src/util/tag-name';
23+
import {Version} from '../../src/version';
24+
import {assertHasUpdate, buildMockConventionalCommit} from '../helpers';
25+
26+
const sandbox = sinon.createSandbox();
27+
28+
const COMMITS = [
29+
...buildMockConventionalCommit(
30+
'fix(deps): update dependency com.google.cloud:google-cloud-storage to v1.120.0'
31+
),
32+
...buildMockConventionalCommit(
33+
'fix(deps): update dependency com.google.cloud:google-cloud-spanner to v1.50.0'
34+
),
35+
...buildMockConventionalCommit('chore: update common templates'),
36+
];
37+
38+
describe('Bazel', () => {
39+
let github: GitHub;
40+
beforeEach(async () => {
41+
github = await GitHub.create({
42+
owner: 'googleapis',
43+
repo: 'bazel-test-repo',
44+
defaultBranch: 'main',
45+
});
46+
});
47+
afterEach(() => {
48+
sandbox.restore();
49+
});
50+
describe('buildReleasePullRequest', () => {
51+
it('returns release PR changes with defaultInitialVersion', async () => {
52+
const expectedVersion = '1.0.0';
53+
const strategy = new Bazel({
54+
targetBranch: 'main',
55+
github,
56+
component: 'rules_cc',
57+
});
58+
const latestRelease = undefined;
59+
const release = await strategy.buildReleasePullRequest(
60+
COMMITS,
61+
latestRelease
62+
);
63+
expect(release!.version?.toString()).to.eql(expectedVersion);
64+
});
65+
it('returns release PR changes with semver patch bump', async () => {
66+
const expectedVersion = '0.123.5';
67+
const strategy = new Bazel({
68+
targetBranch: 'main',
69+
github,
70+
component: 'rules_cc',
71+
});
72+
const latestRelease = {
73+
tag: new TagName(Version.parse('0.123.4'), 'rules_cc'),
74+
sha: 'abc123',
75+
notes: 'some notes',
76+
};
77+
const release = await strategy.buildReleasePullRequest(
78+
COMMITS,
79+
latestRelease
80+
);
81+
expect(release!.version?.toString()).to.eql(expectedVersion);
82+
});
83+
});
84+
describe('buildUpdates', () => {
85+
it('builds common files', async () => {
86+
const strategy = new Bazel({
87+
targetBranch: 'main',
88+
github,
89+
component: 'rules_cc',
90+
});
91+
const latestRelease = undefined;
92+
const release = await strategy.buildReleasePullRequest(
93+
COMMITS,
94+
latestRelease
95+
);
96+
const updates = release!.updates;
97+
assertHasUpdate(updates, 'CHANGELOG.md', Changelog);
98+
assertHasUpdate(updates, 'MODULE.bazel', ModuleBazel);
99+
});
100+
it('allows configuring the version file', async () => {
101+
const strategy = new Bazel({
102+
targetBranch: 'main',
103+
github,
104+
component: 'rules_cc',
105+
versionFile: 'some-path/MODULE.bazel',
106+
path: 'packages',
107+
});
108+
const latestRelease = undefined;
109+
const release = await strategy.buildReleasePullRequest(
110+
COMMITS,
111+
latestRelease
112+
);
113+
const updates = release!.updates;
114+
assertHasUpdate(updates, 'packages/CHANGELOG.md', Changelog);
115+
assertHasUpdate(updates, 'packages/some-path/MODULE.bazel', ModuleBazel);
116+
});
117+
});
118+
});
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module(name = "rules_cc", version = "0.0.4")
2+
3+
bazel_dep(name = "bazel_skylib", version = "1.3.0")
4+
bazel_dep(name = "platforms", version = "0.0.7")
5+
6+
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
7+
use_repo(cc_configure, "local_config_cc_toolchains")
8+
9+
register_toolchains("@local_config_cc_toolchains//:all")
10+
11+
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
bazel_dep(name = "bazel_skylib", version = "1.3.0")
2+
bazel_dep(name = "platforms", version = "0.0.7")
3+
4+
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
5+
use_repo(cc_configure, "local_config_cc_toolchains")
6+
7+
register_toolchains("@local_config_cc_toolchains//:all")
8+
9+
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
bazel_dep(name = "bazel_skylib", version = "1.3.0")
2+
bazel_dep(name = "platforms", version = "0.0.7")
3+
4+
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
5+
use_repo(cc_configure, "local_config_cc_toolchains")
6+
7+
module(name = "rules_cc", version = "0.0.4")
8+
9+
register_toolchains("@local_config_cc_toolchains//:all")
10+
11+
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)

test/updaters/fixtures/MODULE.bazel

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module(
2+
name = "rules_cc",
3+
version = "0.0.4",
4+
compatibility_level = 1,
5+
)
6+
7+
bazel_dep(name = "bazel_skylib", version = "1.3.0")
8+
bazel_dep(name = "platforms", version = "0.0.7")
9+
10+
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
11+
use_repo(cc_configure, "local_config_cc_toolchains")
12+
13+
register_toolchains("@local_config_cc_toolchains//:all")
14+
15+
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)

0 commit comments

Comments
 (0)