Skip to content

Commit

Permalink
feat: add support for bazel (#2239)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrandolf-2 authored Mar 11, 2024
1 parent 3569f15 commit b12904a
Show file tree
Hide file tree
Showing 12 changed files with 390 additions and 20 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ Release Please automates releases for the following flavors of repositories:

| release type | description |
|---------------------|---------------------------------------------------------|
| `bazel` | [A Bazel module, with a MODULE.bazel and a CHANGELOG.md](https://bazel.build/external/module) |
| `dart` | A repository with a pubspec.yaml and a CHANGELOG.md |
| `elixir` | A repository with a mix.exs and a CHANGELOG.md |
| `go` | A repository with a CHANGELOG.md |
Expand Down
8 changes: 4 additions & 4 deletions __snapshots__/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ Options:
[string]
--release-type what type of repo is a release being created
for?
[choices: "dart", "dotnet-yoshi", "elixir", "expo", "go", "go-yoshi", "helm",
"java", "java-backport", "java-bom", "java-lts", "java-yoshi",
[choices: "bazel", "dart", "dotnet-yoshi", "elixir", "expo", "go", "go-yoshi",
"helm", "java", "java-backport", "java-bom", "java-lts", "java-yoshi",
"java-yoshi-mono-repo", "krm-blueprint", "maven", "node", "ocaml", "php",
"php-yoshi", "python", "ruby", "ruby-yoshi", "rust", "salesforce", "sfdx",
"simple", "terraform-module"]
Expand Down Expand Up @@ -241,8 +241,8 @@ Options:
[string]
--release-type what type of repo is a release being created
for?
[choices: "dart", "dotnet-yoshi", "elixir", "expo", "go", "go-yoshi", "helm",
"java", "java-backport", "java-bom", "java-lts", "java-yoshi",
[choices: "bazel", "dart", "dotnet-yoshi", "elixir", "expo", "go", "go-yoshi",
"helm", "java", "java-backport", "java-bom", "java-lts", "java-yoshi",
"java-yoshi-mono-repo", "krm-blueprint", "maven", "node", "ocaml", "php",
"php-yoshi", "python", "ruby", "ruby-yoshi", "rust", "salesforce", "sfdx",
"simple", "terraform-module"]
Expand Down
45 changes: 45 additions & 0 deletions __snapshots__/module-bazel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
exports['ModuleBazel updateContent updates version in MODULE.bazel file 1'] = `
module(
name = "rules_cc",
version = "0.0.5",
compatibility_level = 1,
)
bazel_dep(name = "bazel_skylib", version = "1.3.0")
bazel_dep(name = "platforms", version = "0.0.7")
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc_toolchains")
register_toolchains("@local_config_cc_toolchains//:all")
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
`

exports['ModuleBazel updateContent updates version when inline 1'] = `
module(name = "rules_cc", version = "0.0.5")
bazel_dep(name = "bazel_skylib", version = "1.3.0")
bazel_dep(name = "platforms", version = "0.0.7")
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc_toolchains")
register_toolchains("@local_config_cc_toolchains//:all")
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
`

exports['ModuleBazel updateContent updates version when ordered improperly 1'] = `
bazel_dep(name = "bazel_skylib", version = "1.3.0")
bazel_dep(name = "platforms", version = "0.0.7")
cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc_toolchains")
module(name = "rules_cc", version = "0.0.5")
register_toolchains("@local_config_cc_toolchains//:all")
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
`
34 changes: 18 additions & 16 deletions src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import {Strategy} from './strategy';
import {ConfigurationError} from './errors';
import {buildChangelogNotes} from './factories/changelog-notes-factory';
import {buildVersioningStrategy} from './factories/versioning-strategy-factory';
import {GitHub} from './github';
import {ReleaserConfig} from './manifest';
import {BaseStrategyOptions} from './strategies/base';
import {Bazel} from './strategies/bazel';
import {Dart} from './strategies/dart';
import {DotnetYoshi} from './strategies/dotnet-yoshi';
import {Elixir} from './strategies/elixir';
import {Expo} from './strategies/expo';
import {Go} from './strategies/go';
import {GoYoshi} from './strategies/go-yoshi';
import {Helm} from './strategies/helm';
import {Java} from './strategies/java';
import {JavaYoshi} from './strategies/java-yoshi';
import {JavaYoshiMonoRepo} from './strategies/java-yoshi-mono-repo';
import {KRMBlueprint} from './strategies/krm-blueprint';
import {Maven} from './strategies/maven';
import {Node} from './strategies/node';
import {OCaml} from './strategies/ocaml';
import {PHP} from './strategies/php';
import {PHPYoshi} from './strategies/php-yoshi';
Expand All @@ -28,23 +42,10 @@ import {Rust} from './strategies/rust';
import {Sfdx} from './strategies/sfdx';
import {Simple} from './strategies/simple';
import {TerraformModule} from './strategies/terraform-module';
import {Helm} from './strategies/helm';
import {Elixir} from './strategies/elixir';
import {Dart} from './strategies/dart';
import {Node} from './strategies/node';
import {Expo} from './strategies/expo';
import {GitHub} from './github';
import {ReleaserConfig} from './manifest';
import {Strategy} from './strategy';
import {AlwaysBumpPatch} from './versioning-strategies/always-bump-patch';
import {ServicePackVersioningStrategy} from './versioning-strategies/service-pack';
import {DependencyManifest} from './versioning-strategies/dependency-manifest';
import {BaseStrategyOptions} from './strategies/base';
import {DotnetYoshi} from './strategies/dotnet-yoshi';
import {Java} from './strategies/java';
import {Maven} from './strategies/maven';
import {buildVersioningStrategy} from './factories/versioning-strategy-factory';
import {buildChangelogNotes} from './factories/changelog-notes-factory';
import {ConfigurationError} from './errors';
import {ServicePackVersioningStrategy} from './versioning-strategies/service-pack';

export * from './factories/changelog-notes-factory';
export * from './factories/plugin-factory';
Expand Down Expand Up @@ -107,6 +108,7 @@ const releasers: Record<string, ReleaseBuilder> = {
helm: options => new Helm(options),
elixir: options => new Elixir(options),
dart: options => new Dart(options),
bazel: options => new Bazel(options),
};

export async function buildStrategy(
Expand Down
51 changes: 51 additions & 0 deletions src/strategies/bazel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {Update} from '../update';
import {ModuleBazel} from '../updaters/bazel/module-bazel';
import {Changelog} from '../updaters/changelog';
import {BaseStrategy, BaseStrategyOptions, BuildUpdatesOptions} from './base';

export class Bazel extends BaseStrategy {
readonly versionFile: string;
constructor(options: BaseStrategyOptions) {
super(options);
this.versionFile = options.versionFile ?? 'MODULE.bazel';
}
protected async buildUpdates(
options: BuildUpdatesOptions
): Promise<Update[]> {
const updates: Update[] = [];
const version = options.newVersion;

updates.push({
path: this.addPath(this.changelogPath),
createIfMissing: true,
updater: new Changelog({
version,
changelogEntry: options.changelogEntry,
}),
});

updates.push({
path: this.addPath(this.versionFile),
createIfMissing: false,
updater: new ModuleBazel({
version,
}),
});

return updates;
}
}
32 changes: 32 additions & 0 deletions src/updaters/bazel/module-bazel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {DefaultUpdater} from '../default';

/**
* Updates a Bazel Module file.
*/
export class ModuleBazel extends DefaultUpdater {
updateContent(content: string): string {
const match = content.match(
/module[\s\S]*?\([\s\S]*?version\s*=\s*(['"])(.*?)\1/m
);
if (!match) {
return content;
}
const [fullMatch, , version] = match;
const module = fullMatch.replace(version, this.version.toString());
return content.replace(fullMatch, module);
}
}
118 changes: 118 additions & 0 deletions test/strategies/bazel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import {expect} from 'chai';
import {afterEach, beforeEach, describe, it} from 'mocha';
import * as sinon from 'sinon';
import {GitHub} from '../../src/github';
import {Bazel} from '../../src/strategies/bazel';
import {ModuleBazel} from '../../src/updaters/bazel/module-bazel';
import {Changelog} from '../../src/updaters/changelog';
import {TagName} from '../../src/util/tag-name';
import {Version} from '../../src/version';
import {assertHasUpdate, buildMockConventionalCommit} from '../helpers';

const sandbox = sinon.createSandbox();

const COMMITS = [
...buildMockConventionalCommit(
'fix(deps): update dependency com.google.cloud:google-cloud-storage to v1.120.0'
),
...buildMockConventionalCommit(
'fix(deps): update dependency com.google.cloud:google-cloud-spanner to v1.50.0'
),
...buildMockConventionalCommit('chore: update common templates'),
];

describe('Bazel', () => {
let github: GitHub;
beforeEach(async () => {
github = await GitHub.create({
owner: 'googleapis',
repo: 'bazel-test-repo',
defaultBranch: 'main',
});
});
afterEach(() => {
sandbox.restore();
});
describe('buildReleasePullRequest', () => {
it('returns release PR changes with defaultInitialVersion', async () => {
const expectedVersion = '1.0.0';
const strategy = new Bazel({
targetBranch: 'main',
github,
component: 'rules_cc',
});
const latestRelease = undefined;
const release = await strategy.buildReleasePullRequest(
COMMITS,
latestRelease
);
expect(release!.version?.toString()).to.eql(expectedVersion);
});
it('returns release PR changes with semver patch bump', async () => {
const expectedVersion = '0.123.5';
const strategy = new Bazel({
targetBranch: 'main',
github,
component: 'rules_cc',
});
const latestRelease = {
tag: new TagName(Version.parse('0.123.4'), 'rules_cc'),
sha: 'abc123',
notes: 'some notes',
};
const release = await strategy.buildReleasePullRequest(
COMMITS,
latestRelease
);
expect(release!.version?.toString()).to.eql(expectedVersion);
});
});
describe('buildUpdates', () => {
it('builds common files', async () => {
const strategy = new Bazel({
targetBranch: 'main',
github,
component: 'rules_cc',
});
const latestRelease = undefined;
const release = await strategy.buildReleasePullRequest(
COMMITS,
latestRelease
);
const updates = release!.updates;
assertHasUpdate(updates, 'CHANGELOG.md', Changelog);
assertHasUpdate(updates, 'MODULE.bazel', ModuleBazel);
});
it('allows configuring the version file', async () => {
const strategy = new Bazel({
targetBranch: 'main',
github,
component: 'rules_cc',
versionFile: 'some-path/MODULE.bazel',
path: 'packages',
});
const latestRelease = undefined;
const release = await strategy.buildReleasePullRequest(
COMMITS,
latestRelease
);
const updates = release!.updates;
assertHasUpdate(updates, 'packages/CHANGELOG.md', Changelog);
assertHasUpdate(updates, 'packages/some-path/MODULE.bazel', ModuleBazel);
});
});
});
11 changes: 11 additions & 0 deletions test/updaters/fixtures/MODULE-inline.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module(name = "rules_cc", version = "0.0.4")

bazel_dep(name = "bazel_skylib", version = "1.3.0")
bazel_dep(name = "platforms", version = "0.0.7")

cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc_toolchains")

register_toolchains("@local_config_cc_toolchains//:all")

bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
9 changes: 9 additions & 0 deletions test/updaters/fixtures/MODULE-missing.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
bazel_dep(name = "bazel_skylib", version = "1.3.0")
bazel_dep(name = "platforms", version = "0.0.7")

cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc_toolchains")

register_toolchains("@local_config_cc_toolchains//:all")

bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
11 changes: 11 additions & 0 deletions test/updaters/fixtures/MODULE-order.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
bazel_dep(name = "bazel_skylib", version = "1.3.0")
bazel_dep(name = "platforms", version = "0.0.7")

cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc_toolchains")

module(name = "rules_cc", version = "0.0.4")

register_toolchains("@local_config_cc_toolchains//:all")

bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
15 changes: 15 additions & 0 deletions test/updaters/fixtures/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module(
name = "rules_cc",
version = "0.0.4",
compatibility_level = 1,
)

bazel_dep(name = "bazel_skylib", version = "1.3.0")
bazel_dep(name = "platforms", version = "0.0.7")

cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
use_repo(cc_configure, "local_config_cc_toolchains")

register_toolchains("@local_config_cc_toolchains//:all")

bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
Loading

0 comments on commit b12904a

Please sign in to comment.