release-please 13.16.6 → 13.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,33 @@
4
4
 
5
5
  [1]: https://www.npmjs.com/package/release-please?activeTab=versions
6
6
 
7
+ ## [13.18.0](https://github.com/googleapis/release-please/compare/v13.17.1...v13.18.0) (2022-06-01)
8
+
9
+
10
+ ### Features
11
+
12
+ * add support for generic yaml updater ([#1452](https://github.com/googleapis/release-please/issues/1452)) ([002231a](https://github.com/googleapis/release-please/commit/002231acfa49b3859a7eaee184a2b520eb6611d3))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * fix parsing of tags with major versions higher than 9 ([#1451](https://github.com/googleapis/release-please/issues/1451)) ([5fc402a](https://github.com/googleapis/release-please/commit/5fc402ae41cd5aba4be5155f90fbc39f9369817d))
18
+
19
+ ### [13.17.1](https://github.com/googleapis/release-please/compare/v13.17.0...v13.17.1) (2022-05-27)
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * **deps:** headings are now always H2 ([#1454](https://github.com/googleapis/release-please/issues/1454)) ([32a2fe4](https://github.com/googleapis/release-please/commit/32a2fe497b51be7def2646c1aceebd9c5c6a167e)), closes [#1389](https://github.com/googleapis/release-please/issues/1389)
25
+
26
+ ## [13.17.0](https://github.com/googleapis/release-please/compare/v13.16.6...v13.17.0) (2022-05-24)
27
+
28
+
29
+ ### Features
30
+
31
+ * add maven-workspace plugin ([#1446](https://github.com/googleapis/release-please/issues/1446)) ([ef4d728](https://github.com/googleapis/release-please/commit/ef4d7283143d6ca70c3b894322975a9a2852dfaa))
32
+ * PomXml updater can update dependency versions ([ef4d728](https://github.com/googleapis/release-please/commit/ef4d7283143d6ca70c3b894322975a9a2852dfaa))
33
+
7
34
  ### [13.16.6](https://github.com/googleapis/release-please/compare/v13.16.5...v13.16.6) (2022-05-24)
8
35
 
9
36
 
@@ -17,10 +17,12 @@ exports.getPluginTypes = exports.unregisterPlugin = exports.registerPlugin = exp
17
17
  const linked_versions_1 = require("../plugins/linked-versions");
18
18
  const cargo_workspace_1 = require("../plugins/cargo-workspace");
19
19
  const node_workspace_1 = require("../plugins/node-workspace");
20
+ const maven_workspace_1 = require("../plugins/maven-workspace");
20
21
  const pluginFactories = {
21
22
  'linked-versions': options => new linked_versions_1.LinkedVersions(options.github, options.targetBranch, options.repositoryConfig, options.type.groupName, options.type.components),
22
23
  'cargo-workspace': options => new cargo_workspace_1.CargoWorkspace(options.github, options.targetBranch, options.repositoryConfig, options),
23
24
  'node-workspace': options => new node_workspace_1.NodeWorkspace(options.github, options.targetBranch, options.repositoryConfig, options),
25
+ 'maven-workspace': options => new maven_workspace_1.MavenWorkspace(options.github, options.targetBranch, options.repositoryConfig, options),
24
26
  };
25
27
  function buildPlugin(options) {
26
28
  if (typeof options.type === 'object') {
@@ -10,6 +10,11 @@ declare type ExtraJsonFile = {
10
10
  path: string;
11
11
  jsonpath: string;
12
12
  };
13
+ declare type ExtraYamlFile = {
14
+ type: 'yaml';
15
+ path: string;
16
+ jsonpath: string;
17
+ };
13
18
  declare type ExtraXmlFile = {
14
19
  type: 'xml';
15
20
  path: string;
@@ -19,7 +24,7 @@ declare type ExtraPomFile = {
19
24
  type: 'pom';
20
25
  path: string;
21
26
  };
22
- export declare type ExtraFile = string | ExtraJsonFile | ExtraXmlFile | ExtraPomFile;
27
+ export declare type ExtraFile = string | ExtraJsonFile | ExtraYamlFile | ExtraXmlFile | ExtraPomFile;
23
28
  /**
24
29
  * These are configurations provided to each strategy per-path.
25
30
  */
@@ -48,7 +48,7 @@ class CargoWorkspace extends workspace_1.WorkspacePlugin {
48
48
  const members = cargoManifest.workspace.members;
49
49
  members.push(manifest_1.ROOT_PROJECT_PATH);
50
50
  for (const path of members) {
51
- const manifestPath = addPath(path, 'Cargo.toml');
51
+ const manifestPath = (0, workspace_1.addPath)(path, 'Cargo.toml');
52
52
  logger_1.logger.info(`looking for candidate with path: ${path}`);
53
53
  const candidate = candidates.find(c => c.path === path);
54
54
  // get original content of the crate
@@ -100,13 +100,13 @@ class CargoWorkspace extends workspace_1.WorkspacePlugin {
100
100
  const dependencyNotes = getChangelogDepsNotes(originalManifest, updatedManifest);
101
101
  existingCandidate.pullRequest.updates =
102
102
  existingCandidate.pullRequest.updates.map(update => {
103
- if (update.path === addPath(existingCandidate.path, 'Cargo.toml')) {
103
+ if (update.path === (0, workspace_1.addPath)(existingCandidate.path, 'Cargo.toml')) {
104
104
  update.updater = new raw_content_1.RawContent(updatedContent);
105
105
  }
106
106
  else if (update.updater instanceof changelog_1.Changelog && dependencyNotes) {
107
- update.updater.changelogEntry = appendDependenciesSectionToChangelog(update.updater.changelogEntry, dependencyNotes);
107
+ update.updater.changelogEntry = (0, workspace_1.appendDependenciesSectionToChangelog)(update.updater.changelogEntry, dependencyNotes);
108
108
  }
109
- else if (update.path === addPath(existingCandidate.path, 'Cargo.lock')) {
109
+ else if (update.path === (0, workspace_1.addPath)(existingCandidate.path, 'Cargo.lock')) {
110
110
  update.updater = new cargo_lock_1.CargoLock(updatedVersions);
111
111
  }
112
112
  return update;
@@ -115,13 +115,13 @@ class CargoWorkspace extends workspace_1.WorkspacePlugin {
115
115
  if (dependencyNotes) {
116
116
  if (existingCandidate.pullRequest.body.releaseData.length > 0) {
117
117
  existingCandidate.pullRequest.body.releaseData[0].notes =
118
- appendDependenciesSectionToChangelog(existingCandidate.pullRequest.body.releaseData[0].notes, dependencyNotes);
118
+ (0, workspace_1.appendDependenciesSectionToChangelog)(existingCandidate.pullRequest.body.releaseData[0].notes, dependencyNotes);
119
119
  }
120
120
  else {
121
121
  existingCandidate.pullRequest.body.releaseData.push({
122
122
  component: pkg.name,
123
123
  version: existingCandidate.pullRequest.version,
124
- notes: appendDependenciesSectionToChangelog('', dependencyNotes),
124
+ notes: (0, workspace_1.appendDependenciesSectionToChangelog)('', dependencyNotes),
125
125
  });
126
126
  }
127
127
  }
@@ -146,17 +146,17 @@ class CargoWorkspace extends workspace_1.WorkspacePlugin {
146
146
  {
147
147
  component: pkg.name,
148
148
  version,
149
- notes: appendDependenciesSectionToChangelog('', dependencyNotes),
149
+ notes: (0, workspace_1.appendDependenciesSectionToChangelog)('', dependencyNotes),
150
150
  },
151
151
  ]),
152
152
  updates: [
153
153
  {
154
- path: addPath(pkg.path, 'Cargo.toml'),
154
+ path: (0, workspace_1.addPath)(pkg.path, 'Cargo.toml'),
155
155
  createIfMissing: false,
156
156
  updater: new raw_content_1.RawContent(updatedContent),
157
157
  },
158
158
  {
159
- path: addPath(pkg.path, 'CHANGELOG.md'),
159
+ path: (0, workspace_1.addPath)(pkg.path, 'CHANGELOG.md'),
160
160
  createIfMissing: false,
161
161
  updater: new changelog_1.Changelog({
162
162
  version,
@@ -275,42 +275,4 @@ function getChangelogDepsNotes(originalManifest, updatedManifest) {
275
275
  }
276
276
  return '';
277
277
  }
278
- const DEPENDENCY_HEADER = new RegExp('### Dependencies');
279
- function appendDependenciesSectionToChangelog(changelog, notes) {
280
- if (!changelog) {
281
- return `### Dependencies\n\n${notes}`;
282
- }
283
- const newLines = [];
284
- let seenDependenciesSection = false;
285
- let seenDependencySectionSpacer = false;
286
- let injected = false;
287
- for (const line of changelog.split('\n')) {
288
- if (seenDependenciesSection) {
289
- const trimmedLine = line.trim();
290
- if (seenDependencySectionSpacer &&
291
- !injected &&
292
- !trimmedLine.startsWith('*')) {
293
- newLines.push(changelog);
294
- injected = true;
295
- }
296
- if (trimmedLine === '') {
297
- seenDependencySectionSpacer = true;
298
- }
299
- }
300
- if (line.match(DEPENDENCY_HEADER)) {
301
- seenDependenciesSection = true;
302
- }
303
- newLines.push(line);
304
- }
305
- if (injected) {
306
- return newLines.join('\n');
307
- }
308
- if (seenDependenciesSection) {
309
- return `${changelog}\n${notes}`;
310
- }
311
- return `${changelog}\n\n\n### Dependencies\n\n${notes}`;
312
- }
313
- function addPath(path, file) {
314
- return path === manifest_1.ROOT_PROJECT_PATH ? file : `${path}/${file}`;
315
- }
316
278
  //# sourceMappingURL=cargo-workspace.js.map
@@ -0,0 +1,28 @@
1
+ import { WorkspacePlugin, AllPackages, DependencyGraph } from './workspace';
2
+ import { Version, VersionsMap } from '../version';
3
+ import { CandidateReleasePullRequest } from '../manifest';
4
+ interface Gav {
5
+ groupId: string;
6
+ artifactId: string;
7
+ version: string;
8
+ }
9
+ interface MavenArtifact extends Gav {
10
+ path: string;
11
+ name: string;
12
+ dependencies: Gav[];
13
+ testDependencies: Gav[];
14
+ pomContent: string;
15
+ }
16
+ export declare class MavenWorkspace extends WorkspacePlugin<MavenArtifact> {
17
+ private fetchPom;
18
+ protected buildAllPackages(candidates: CandidateReleasePullRequest[]): Promise<AllPackages<MavenArtifact>>;
19
+ protected buildGraph(allPackages: MavenArtifact[]): Promise<DependencyGraph<MavenArtifact>>;
20
+ protected bumpVersion(artifact: MavenArtifact): Version;
21
+ protected updateCandidate(existingCandidate: CandidateReleasePullRequest, artifact: MavenArtifact, updatedVersions: VersionsMap): CandidateReleasePullRequest;
22
+ protected newCandidate(artifact: MavenArtifact, updatedVersions: VersionsMap): CandidateReleasePullRequest;
23
+ protected inScope(candidate: CandidateReleasePullRequest): boolean;
24
+ protected packageNameFromPackage(artifact: MavenArtifact): string;
25
+ protected pathFromPackage(artifact: MavenArtifact): string;
26
+ protected postProcessCandidates(candidates: CandidateReleasePullRequest[], _updatedVersions: VersionsMap): CandidateReleasePullRequest[];
27
+ }
28
+ export {};
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ // Copyright 2022 Google LLC
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.MavenWorkspace = void 0;
17
+ const workspace_1 = require("./workspace");
18
+ const version_1 = require("../version");
19
+ const versioning_strategy_1 = require("../versioning-strategy");
20
+ const dom = require("@xmldom/xmldom");
21
+ const xpath = require("xpath");
22
+ const logger_1 = require("../util/logger");
23
+ const path_1 = require("path");
24
+ const pom_xml_1 = require("../updaters/java/pom-xml");
25
+ const changelog_1 = require("../updaters/changelog");
26
+ const pull_request_title_1 = require("../util/pull-request-title");
27
+ const pull_request_body_1 = require("../util/pull-request-body");
28
+ const branch_name_1 = require("../util/branch-name");
29
+ const JAVA_RELEASE_TYPES = new Set(['java', 'java-bom', 'java-yoshi', 'maven']);
30
+ const XPATH_PROJECT_GROUP = '/*[local-name()="project"]/*[local-name()="groupId"]';
31
+ const XPATH_PROJECT_ARTIFACT = '/*[local-name()="project"]/*[local-name()="artifactId"]';
32
+ const XPATH_PROJECT_VERSION = '/*[local-name()="project"]/*[local-name()="version"]';
33
+ const XPATH_PROJECT_DEPENDENCIES = '/*[local-name()="project"]/*[local-name()="dependencies"]/*[local-name()="dependency"]';
34
+ class MavenWorkspace extends workspace_1.WorkspacePlugin {
35
+ async fetchPom(path) {
36
+ const content = await this.github.getFileContentsOnBranch(path, this.targetBranch);
37
+ const document = new dom.DOMParser().parseFromString(content.parsedContent);
38
+ const groupNodes = xpath.select(XPATH_PROJECT_GROUP, document);
39
+ if (groupNodes.length === 0) {
40
+ logger_1.logger.warn(`Missing project.groupId in ${path}`);
41
+ return;
42
+ }
43
+ const artifactNodes = xpath.select(XPATH_PROJECT_ARTIFACT, document);
44
+ if (artifactNodes.length === 0) {
45
+ logger_1.logger.warn(`Missing project.artifactId in ${path}`);
46
+ return;
47
+ }
48
+ const versionNodes = xpath.select(XPATH_PROJECT_VERSION, document);
49
+ if (versionNodes.length === 0) {
50
+ logger_1.logger.warn(`Missing project.version in ${path}`);
51
+ return;
52
+ }
53
+ const dependencies = [];
54
+ const testDependencies = [];
55
+ for (const dependencyNode of xpath.select(XPATH_PROJECT_DEPENDENCIES, document)) {
56
+ const parsedNode = (0, pom_xml_1.parseDependencyNode)(dependencyNode);
57
+ if (!parsedNode.version) {
58
+ continue;
59
+ }
60
+ if (parsedNode.scope === 'test') {
61
+ testDependencies.push({
62
+ groupId: parsedNode.groupId,
63
+ artifactId: parsedNode.artifactId,
64
+ version: parsedNode.version,
65
+ });
66
+ }
67
+ else {
68
+ dependencies.push({
69
+ groupId: parsedNode.groupId,
70
+ artifactId: parsedNode.artifactId,
71
+ version: parsedNode.version,
72
+ });
73
+ }
74
+ }
75
+ const groupId = groupNodes[0].firstChild.textContent;
76
+ const artifactId = artifactNodes[0].firstChild.textContent;
77
+ return {
78
+ path,
79
+ groupId,
80
+ artifactId,
81
+ name: `${groupId}:${artifactId}`,
82
+ version: versionNodes[0].firstChild.textContent,
83
+ dependencies,
84
+ testDependencies,
85
+ pomContent: content.parsedContent,
86
+ };
87
+ }
88
+ async buildAllPackages(candidates) {
89
+ const allPackages = [];
90
+ const candidatesByPackage = {};
91
+ // find all pom.xml files and build a dependency graph
92
+ const pomFiles = await this.github.findFilesByFilenameAndRef('pom.xml', this.targetBranch);
93
+ for (const pomFile of pomFiles) {
94
+ const path = (0, path_1.dirname)(pomFile);
95
+ const config = this.repositoryConfig[path];
96
+ if (!config) {
97
+ logger_1.logger.info(`path '${path}' not configured, ignoring '${pomFile}'`);
98
+ continue;
99
+ }
100
+ const mavenArtifact = await this.fetchPom(pomFile);
101
+ if (!mavenArtifact) {
102
+ continue;
103
+ }
104
+ allPackages.push(mavenArtifact);
105
+ const candidate = candidates.find(candidate => candidate.path === path);
106
+ if (candidate) {
107
+ candidatesByPackage[this.packageNameFromPackage(mavenArtifact)] =
108
+ candidate;
109
+ }
110
+ else {
111
+ logger_1.logger.warn(`found ${pomFile} in path ${path}, but did not find an associated candidate PR`);
112
+ }
113
+ }
114
+ return {
115
+ allPackages,
116
+ candidatesByPackage,
117
+ };
118
+ }
119
+ async buildGraph(allPackages) {
120
+ const artifactsByName = allPackages.reduce((collection, mavenArtifact) => {
121
+ collection[mavenArtifact.name] = mavenArtifact;
122
+ return collection;
123
+ }, {});
124
+ const graph = new Map();
125
+ for (const mavenArtifact of allPackages) {
126
+ const allDeps = [
127
+ ...mavenArtifact.dependencies,
128
+ ...mavenArtifact.testDependencies,
129
+ ];
130
+ const workspaceDeps = allDeps.filter(dep => artifactsByName[packageNameFromGav(dep)]);
131
+ graph.set(mavenArtifact.name, {
132
+ deps: workspaceDeps.map(dep => packageNameFromGav(dep)),
133
+ value: mavenArtifact,
134
+ });
135
+ }
136
+ return graph;
137
+ }
138
+ bumpVersion(artifact) {
139
+ const version = version_1.Version.parse(artifact.version);
140
+ return new versioning_strategy_1.PatchVersionUpdate().bump(version);
141
+ }
142
+ updateCandidate(existingCandidate, artifact, updatedVersions) {
143
+ const version = updatedVersions.get(artifact.name);
144
+ if (!version) {
145
+ throw new Error(`Didn't find updated version for ${artifact.name}`);
146
+ }
147
+ const updater = new pom_xml_1.PomXml(version, updatedVersions);
148
+ const dependencyNotes = getChangelogDepsNotes(artifact, updater, updatedVersions);
149
+ existingCandidate.pullRequest.updates =
150
+ existingCandidate.pullRequest.updates.map(update => {
151
+ if (update.path === (0, workspace_1.addPath)(existingCandidate.path, 'pom.xml')) {
152
+ update.updater = updater;
153
+ }
154
+ else if (update.updater instanceof changelog_1.Changelog) {
155
+ if (dependencyNotes) {
156
+ update.updater.changelogEntry =
157
+ (0, workspace_1.appendDependenciesSectionToChangelog)(update.updater.changelogEntry, dependencyNotes);
158
+ }
159
+ }
160
+ return update;
161
+ });
162
+ // append dependency notes
163
+ if (dependencyNotes) {
164
+ if (existingCandidate.pullRequest.body.releaseData.length > 0) {
165
+ existingCandidate.pullRequest.body.releaseData[0].notes =
166
+ (0, workspace_1.appendDependenciesSectionToChangelog)(existingCandidate.pullRequest.body.releaseData[0].notes, dependencyNotes);
167
+ }
168
+ else {
169
+ existingCandidate.pullRequest.body.releaseData.push({
170
+ component: artifact.name,
171
+ version: existingCandidate.pullRequest.version,
172
+ notes: (0, workspace_1.appendDependenciesSectionToChangelog)('', dependencyNotes),
173
+ });
174
+ }
175
+ }
176
+ return existingCandidate;
177
+ }
178
+ newCandidate(artifact, updatedVersions) {
179
+ const version = updatedVersions.get(artifact.name);
180
+ if (!version) {
181
+ throw new Error(`Didn't find updated version for ${artifact.name}`);
182
+ }
183
+ const updater = new pom_xml_1.PomXml(version, updatedVersions);
184
+ const dependencyNotes = getChangelogDepsNotes(artifact, updater, updatedVersions);
185
+ const pullRequest = {
186
+ title: pull_request_title_1.PullRequestTitle.ofTargetBranch(this.targetBranch),
187
+ body: new pull_request_body_1.PullRequestBody([
188
+ {
189
+ component: artifact.name,
190
+ version,
191
+ notes: (0, workspace_1.appendDependenciesSectionToChangelog)('', dependencyNotes),
192
+ },
193
+ ]),
194
+ updates: [
195
+ {
196
+ path: (0, workspace_1.addPath)(artifact.path, 'pom.xml'),
197
+ createIfMissing: false,
198
+ updater,
199
+ },
200
+ {
201
+ path: (0, workspace_1.addPath)(artifact.path, 'CHANGELOG.md'),
202
+ createIfMissing: false,
203
+ updater: new changelog_1.Changelog({
204
+ version,
205
+ changelogEntry: dependencyNotes,
206
+ }),
207
+ },
208
+ ],
209
+ labels: [],
210
+ headRefName: branch_name_1.BranchName.ofTargetBranch(this.targetBranch).toString(),
211
+ version,
212
+ draft: false,
213
+ };
214
+ return {
215
+ path: artifact.path,
216
+ pullRequest,
217
+ config: {
218
+ releaseType: 'maven',
219
+ },
220
+ };
221
+ }
222
+ inScope(candidate) {
223
+ return JAVA_RELEASE_TYPES.has(candidate.config.releaseType);
224
+ }
225
+ packageNameFromPackage(artifact) {
226
+ return artifact.name;
227
+ }
228
+ pathFromPackage(artifact) {
229
+ return artifact.path;
230
+ }
231
+ postProcessCandidates(candidates, _updatedVersions) {
232
+ // NOP for maven workspaces
233
+ return candidates;
234
+ }
235
+ }
236
+ exports.MavenWorkspace = MavenWorkspace;
237
+ function packageNameFromGav(gav) {
238
+ return `${gav.groupId}:${gav.artifactId}`;
239
+ }
240
+ function getChangelogDepsNotes(artifact, updater, updatedVersions) {
241
+ const document = new dom.DOMParser().parseFromString(artifact.pomContent);
242
+ const dependencyUpdates = updater.dependencyUpdates(document, updatedVersions);
243
+ const depUpdateNotes = [];
244
+ for (const dependencyUpdate of dependencyUpdates) {
245
+ depUpdateNotes.push(`\n * ${dependencyUpdate.name} bumped to ${dependencyUpdate.version}`);
246
+ logger_1.logger.info(`bumped ${dependencyUpdate.name} to ${dependencyUpdate.version}`);
247
+ }
248
+ if (depUpdateNotes.length > 0) {
249
+ return `* The following workspace dependencies were updated${depUpdateNotes.join()}`;
250
+ }
251
+ return '';
252
+ }
253
+ //# sourceMappingURL=maven-workspace.js.map
@@ -63,7 +63,7 @@ class NodeWorkspace extends workspace_1.WorkspacePlugin {
63
63
  const candidate = candidatesByPath.get(path);
64
64
  if (candidate) {
65
65
  logger_1.logger.debug(`Found candidate pull request for path: ${candidate.path}`);
66
- const packagePath = addPath(candidate.path, 'package.json');
66
+ const packagePath = (0, workspace_1.addPath)(candidate.path, 'package.json');
67
67
  const packageUpdate = candidate.pullRequest.updates.find(update => update.path === packagePath);
68
68
  if (packageUpdate === null || packageUpdate === void 0 ? void 0 : packageUpdate.cachedFileContents) {
69
69
  const pkg = new Package(packageUpdate.cachedFileContents.parsedContent, candidate.path);
@@ -78,7 +78,7 @@ class NodeWorkspace extends workspace_1.WorkspacePlugin {
78
78
  }
79
79
  }
80
80
  else {
81
- const packagePath = addPath(path, 'package.json');
81
+ const packagePath = (0, workspace_1.addPath)(path, 'package.json');
82
82
  logger_1.logger.debug(`No candidate pull request for path: ${path} - inspect package from ${packagePath}`);
83
83
  const contents = await this.github.getFileContentsOnBranch(packagePath, this.targetBranch);
84
84
  packagesByPath.set(path, new Package(contents.parsedContent, path));
@@ -119,13 +119,13 @@ class NodeWorkspace extends workspace_1.WorkspacePlugin {
119
119
  const dependencyNotes = getChangelogDepsNotes(pkg, updatedPackage);
120
120
  existingCandidate.pullRequest.updates =
121
121
  existingCandidate.pullRequest.updates.map(update => {
122
- if (update.path === addPath(existingCandidate.path, 'package.json')) {
122
+ if (update.path === (0, workspace_1.addPath)(existingCandidate.path, 'package.json')) {
123
123
  update.updater = new raw_content_1.RawContent((0, json_stringify_1.jsonStringify)(updatedPackage.toJSON(), updatedPackage.rawContent));
124
124
  }
125
125
  else if (update.updater instanceof changelog_1.Changelog) {
126
126
  if (dependencyNotes) {
127
127
  update.updater.changelogEntry =
128
- appendDependenciesSectionToChangelog(update.updater.changelogEntry, dependencyNotes);
128
+ (0, workspace_1.appendDependenciesSectionToChangelog)(update.updater.changelogEntry, dependencyNotes);
129
129
  }
130
130
  }
131
131
  return update;
@@ -134,13 +134,13 @@ class NodeWorkspace extends workspace_1.WorkspacePlugin {
134
134
  if (dependencyNotes) {
135
135
  if (existingCandidate.pullRequest.body.releaseData.length > 0) {
136
136
  existingCandidate.pullRequest.body.releaseData[0].notes =
137
- appendDependenciesSectionToChangelog(existingCandidate.pullRequest.body.releaseData[0].notes, dependencyNotes);
137
+ (0, workspace_1.appendDependenciesSectionToChangelog)(existingCandidate.pullRequest.body.releaseData[0].notes, dependencyNotes);
138
138
  }
139
139
  else {
140
140
  existingCandidate.pullRequest.body.releaseData.push({
141
141
  component: updatedPackage.name,
142
142
  version: existingCandidate.pullRequest.version,
143
- notes: appendDependenciesSectionToChangelog('', dependencyNotes),
143
+ notes: (0, workspace_1.appendDependenciesSectionToChangelog)('', dependencyNotes),
144
144
  });
145
145
  }
146
146
  }
@@ -175,21 +175,21 @@ class NodeWorkspace extends workspace_1.WorkspacePlugin {
175
175
  {
176
176
  component: updatedPackage.name,
177
177
  version,
178
- notes: appendDependenciesSectionToChangelog('', dependencyNotes),
178
+ notes: (0, workspace_1.appendDependenciesSectionToChangelog)('', dependencyNotes),
179
179
  },
180
180
  ]),
181
181
  updates: [
182
182
  {
183
- path: addPath(updatedPackage.location, 'package.json'),
183
+ path: (0, workspace_1.addPath)(updatedPackage.location, 'package.json'),
184
184
  createIfMissing: false,
185
185
  updater: new raw_content_1.RawContent((0, json_stringify_1.jsonStringify)(packageJson, updatedPackage.rawContent)),
186
186
  },
187
187
  {
188
- path: addPath(updatedPackage.location, 'CHANGELOG.md'),
188
+ path: (0, workspace_1.addPath)(updatedPackage.location, 'CHANGELOG.md'),
189
189
  createIfMissing: false,
190
190
  updater: new changelog_1.Changelog({
191
191
  version,
192
- changelogEntry: appendDependenciesSectionToChangelog('', dependencyNotes),
192
+ changelogEntry: (0, workspace_1.appendDependenciesSectionToChangelog)('', dependencyNotes),
193
193
  }),
194
194
  },
195
195
  ],
@@ -277,42 +277,4 @@ function getChangelogDepsNotes(original, updated) {
277
277
  }
278
278
  return '';
279
279
  }
280
- const DEPENDENCY_HEADER = new RegExp('### Dependencies');
281
- function appendDependenciesSectionToChangelog(changelog, notes) {
282
- if (!changelog) {
283
- return `### Dependencies\n\n${notes}`;
284
- }
285
- const newLines = [];
286
- let seenDependenciesSection = false;
287
- let seenDependencySectionSpacer = false;
288
- let injected = false;
289
- for (const line of changelog.split('\n')) {
290
- if (seenDependenciesSection) {
291
- const trimmedLine = line.trim();
292
- if (seenDependencySectionSpacer &&
293
- !injected &&
294
- !trimmedLine.startsWith('*')) {
295
- newLines.push(changelog);
296
- injected = true;
297
- }
298
- if (trimmedLine === '') {
299
- seenDependencySectionSpacer = true;
300
- }
301
- }
302
- if (line.match(DEPENDENCY_HEADER)) {
303
- seenDependenciesSection = true;
304
- }
305
- newLines.push(line);
306
- }
307
- if (injected) {
308
- return newLines.join('\n');
309
- }
310
- if (seenDependenciesSection) {
311
- return `${changelog}\n${notes}`;
312
- }
313
- return `${changelog}\n\n\n### Dependencies\n\n${notes}`;
314
- }
315
- function addPath(path, file) {
316
- return path === manifest_1.ROOT_PROJECT_PATH ? file : `${path}/${file}`;
317
- }
318
280
  //# sourceMappingURL=node-workspace.js.map
@@ -11,7 +11,7 @@ export interface WorkspacePluginOptions {
11
11
  manifestPath?: string;
12
12
  updateAllPackages?: boolean;
13
13
  }
14
- interface AllPackages<T> {
14
+ export interface AllPackages<T> {
15
15
  allPackages: T[];
16
16
  candidatesByPackage: Record<string, CandidateReleasePullRequest>;
17
17
  }
@@ -120,4 +120,5 @@ export declare abstract class WorkspacePlugin<T> extends ManifestPlugin {
120
120
  protected buildGraphOrder(graph: DependencyGraph<T>, packageNamesToUpdate: string[]): T[];
121
121
  private visitPostOrder;
122
122
  }
123
- export {};
123
+ export declare function appendDependenciesSectionToChangelog(changelog: string, notes: string): string;
124
+ export declare function addPath(path: string, file: string): string;
@@ -13,7 +13,7 @@
13
13
  // See the License for the specific language governing permissions and
14
14
  // limitations under the License.
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.WorkspacePlugin = void 0;
16
+ exports.addPath = exports.appendDependenciesSectionToChangelog = exports.WorkspacePlugin = void 0;
17
17
  const plugin_1 = require("../plugin");
18
18
  const manifest_1 = require("../manifest");
19
19
  const logger_1 = require("../util/logger");
@@ -189,4 +189,45 @@ class WorkspacePlugin extends plugin_1.ManifestPlugin {
189
189
  }
190
190
  }
191
191
  exports.WorkspacePlugin = WorkspacePlugin;
192
+ const DEPENDENCY_HEADER = new RegExp('### Dependencies');
193
+ function appendDependenciesSectionToChangelog(changelog, notes) {
194
+ if (!changelog) {
195
+ return `### Dependencies\n\n${notes}`;
196
+ }
197
+ logger_1.logger.info('appending dependency notes to changelog');
198
+ const newLines = [];
199
+ let seenDependenciesSection = false;
200
+ let seenDependencySectionSpacer = false;
201
+ let injected = false;
202
+ for (const line of changelog.split('\n')) {
203
+ if (seenDependenciesSection) {
204
+ const trimmedLine = line.trim();
205
+ if (seenDependencySectionSpacer &&
206
+ !injected &&
207
+ !trimmedLine.startsWith('*')) {
208
+ newLines.push(changelog);
209
+ injected = true;
210
+ }
211
+ if (trimmedLine === '') {
212
+ seenDependencySectionSpacer = true;
213
+ }
214
+ }
215
+ if (line.match(DEPENDENCY_HEADER)) {
216
+ seenDependenciesSection = true;
217
+ }
218
+ newLines.push(line);
219
+ }
220
+ if (injected) {
221
+ return newLines.join('\n');
222
+ }
223
+ if (seenDependenciesSection) {
224
+ return `${changelog}\n${notes}`;
225
+ }
226
+ return `${changelog}\n\n\n### Dependencies\n\n${notes}`;
227
+ }
228
+ exports.appendDependenciesSectionToChangelog = appendDependenciesSectionToChangelog;
229
+ function addPath(path, file) {
230
+ return path === manifest_1.ROOT_PROJECT_PATH ? file : `${path}/${file}`;
231
+ }
232
+ exports.addPath = addPath;
192
233
  //# sourceMappingURL=workspace.js.map
@@ -29,6 +29,7 @@ const generic_1 = require("../updaters/generic");
29
29
  const generic_json_1 = require("../updaters/generic-json");
30
30
  const generic_xml_1 = require("../updaters/generic-xml");
31
31
  const pom_xml_1 = require("../updaters/java/pom-xml");
32
+ const generic_yaml_1 = require("../updaters/generic-yaml");
32
33
  const DEFAULT_CHANGELOG_PATH = 'CHANGELOG.md';
33
34
  /**
34
35
  * A strategy is responsible for determining which files are
@@ -183,6 +184,12 @@ class BaseStrategy {
183
184
  createIfMissing: false,
184
185
  updater: new generic_json_1.GenericJson(extraFile.jsonpath, version),
185
186
  };
187
+ case 'yaml':
188
+ return {
189
+ path: this.addPath(extraFile.path),
190
+ createIfMissing: false,
191
+ updater: new generic_yaml_1.GenericYaml(extraFile.jsonpath, version),
192
+ };
186
193
  case 'xml':
187
194
  return {
188
195
  path: this.addPath(extraFile.path),
@@ -0,0 +1,22 @@
1
+ import { Updater } from '../update';
2
+ import { Version } from '../version';
3
+ /**
4
+ * Updates YAML document according to given JSONPath.
5
+ *
6
+ * Note that used parser does reformat the document and removes all comments,
7
+ * and converts everything to pure YAML (even JSON source).
8
+ * If you want to retain formatting, use generic updater with comment hints.
9
+ *
10
+ * When applied on multi-document file, it updates all documents.
11
+ */
12
+ export declare class GenericYaml implements Updater {
13
+ readonly jsonpath: string;
14
+ readonly version: Version;
15
+ constructor(jsonpath: string, version: Version);
16
+ /**
17
+ * Given initial file contents, return updated contents.
18
+ * @param {string} content The initial content
19
+ * @returns {string} The updated content
20
+ */
21
+ updateContent(content: string): string;
22
+ }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ // Copyright 2022 Google LLC
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.GenericYaml = void 0;
17
+ const jp = require("jsonpath");
18
+ const yaml = require("js-yaml");
19
+ const logger_1 = require("../util/logger");
20
+ const DOCUMENT_SEPARATOR = '---\n';
21
+ /**
22
+ * Updates YAML document according to given JSONPath.
23
+ *
24
+ * Note that used parser does reformat the document and removes all comments,
25
+ * and converts everything to pure YAML (even JSON source).
26
+ * If you want to retain formatting, use generic updater with comment hints.
27
+ *
28
+ * When applied on multi-document file, it updates all documents.
29
+ */
30
+ class GenericYaml {
31
+ constructor(jsonpath, version) {
32
+ this.jsonpath = jsonpath;
33
+ this.version = version;
34
+ }
35
+ /**
36
+ * Given initial file contents, return updated contents.
37
+ * @param {string} content The initial content
38
+ * @returns {string} The updated content
39
+ */
40
+ updateContent(content) {
41
+ // Parse possibly multi-document file
42
+ let docs;
43
+ try {
44
+ docs = yaml.loadAll(content, null, { json: true });
45
+ }
46
+ catch (e) {
47
+ logger_1.logger.warn('Invalid yaml, cannot be parsed', e);
48
+ return content;
49
+ }
50
+ // Update each document
51
+ let modified = false;
52
+ docs.forEach(data => {
53
+ const nodes = jp.apply(data, this.jsonpath, _val => {
54
+ return this.version.toString();
55
+ });
56
+ if (nodes && nodes.length) {
57
+ modified = true;
58
+ }
59
+ });
60
+ // If nothing was modified, return original content
61
+ if (!modified) {
62
+ logger_1.logger.warn(`No entries modified in ${this.jsonpath}`);
63
+ return content;
64
+ }
65
+ // Stringify documents
66
+ if (docs.length === 1) {
67
+ // Single doc
68
+ return yaml.dump(docs[0]);
69
+ }
70
+ else {
71
+ // Multi-document, each document starts with separator
72
+ return docs.map(data => DOCUMENT_SEPARATOR + yaml.dump(data)).join('');
73
+ }
74
+ }
75
+ }
76
+ exports.GenericYaml = GenericYaml;
77
+ //# sourceMappingURL=generic-yaml.js.map
@@ -1,4 +1,4 @@
1
- import { Version } from '../../version';
1
+ import { Version, VersionsMap } from '../../version';
2
2
  import { BaseXml } from '../base-xml';
3
3
  /**
4
4
  * Updates version pom.xml files.
@@ -8,7 +8,22 @@ import { BaseXml } from '../base-xml';
8
8
  */
9
9
  export declare class PomXml extends BaseXml {
10
10
  private readonly version;
11
- constructor(version: Version);
11
+ private readonly dependencyVersions?;
12
+ constructor(version: Version, dependencyVersions?: VersionsMap);
12
13
  protected updateDocument(document: Document): boolean;
14
+ dependencyUpdates(document: Document, updatedVersions: VersionsMap): {
15
+ name: string;
16
+ nodes: Node[];
17
+ version: Version;
18
+ }[];
13
19
  private static updateNodes;
14
20
  }
21
+ interface DependencyNode {
22
+ groupId: string;
23
+ artifactId: string;
24
+ version?: string;
25
+ scope?: string;
26
+ versionNode?: Node;
27
+ }
28
+ export declare function parseDependencyNode(node: Node): DependencyNode;
29
+ export {};
@@ -13,11 +13,13 @@
13
13
  // See the License for the specific language governing permissions and
14
14
  // limitations under the License.
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
- exports.PomXml = void 0;
16
+ exports.parseDependencyNode = exports.PomXml = void 0;
17
17
  const base_xml_1 = require("../base-xml");
18
18
  const xpath = require("xpath");
19
19
  const XPATH_PROJECT_VERSION = '/*[local-name()="project"]/*[local-name()="version"]';
20
20
  const XPATH_PROJECT_PARENT_VERSION = '/*[local-name()="project"]/*[local-name()="parent"]/*[local-name()="version"]';
21
+ const XPATH_PROJECT_DEPENDENCIES = '/*[local-name()="project"]/*[local-name()="dependencies"]/*[local-name()="dependency"]';
22
+ const XPATH_PROJECT_DEPENDENCY_MANAGEMENT_DEPENDENCIES = '/*[local-name()="project"]/*[local-name()="dependencyManagement"]/*[local-name()="dependencies"]/*[local-name()="dependency"]';
21
23
  /**
22
24
  * Updates version pom.xml files.
23
25
  *
@@ -25,22 +27,71 @@ const XPATH_PROJECT_PARENT_VERSION = '/*[local-name()="project"]/*[local-name()=
25
27
  * If project.version is not present, it updates project.parent.version.
26
28
  */
27
29
  class PomXml extends base_xml_1.BaseXml {
28
- constructor(version) {
30
+ constructor(version, dependencyVersions) {
29
31
  super();
30
32
  this.version = version;
33
+ this.dependencyVersions = dependencyVersions;
31
34
  }
32
35
  updateDocument(document) {
33
- const version = this.version.toString();
34
36
  // NOTE this intentionally ignores namespaces - let the maven decide, what's valid and what's not
37
+ const updates = [];
35
38
  // Update project.version
36
39
  const projectVersionNodes = xpath.select(XPATH_PROJECT_VERSION, document);
37
40
  if (projectVersionNodes.length) {
38
41
  // If found update, detect actual change
39
- return PomXml.updateNodes(projectVersionNodes, version);
42
+ updates.push({
43
+ nodes: projectVersionNodes,
44
+ version: this.version,
45
+ });
40
46
  }
41
- // Try updating project.parent.version
42
- const parentVersionNodes = xpath.select(XPATH_PROJECT_PARENT_VERSION, document);
43
- return PomXml.updateNodes(parentVersionNodes, version);
47
+ else {
48
+ // Try updating project.parent.version
49
+ const parentVersionNodes = xpath.select(XPATH_PROJECT_PARENT_VERSION, document);
50
+ updates.push({
51
+ nodes: parentVersionNodes,
52
+ version: this.version,
53
+ });
54
+ }
55
+ if (this.dependencyVersions) {
56
+ updates.push(...this.dependencyUpdates(document, this.dependencyVersions));
57
+ }
58
+ let updated = false;
59
+ for (const { nodes, version } of updates) {
60
+ updated = PomXml.updateNodes(nodes, version.toString()) || updated;
61
+ }
62
+ return updated;
63
+ }
64
+ dependencyUpdates(document, updatedVersions) {
65
+ const updates = [];
66
+ const dependencyNodes = xpath.select(XPATH_PROJECT_DEPENDENCIES, document);
67
+ const dependencyManagementNodes = xpath.select(XPATH_PROJECT_DEPENDENCY_MANAGEMENT_DEPENDENCIES, document);
68
+ // try to update dependency versions
69
+ for (const [name, version] of updatedVersions.entries()) {
70
+ // look under:
71
+ // - project/dependencies
72
+ // - project/dependencyManagement/dependencies
73
+ const [groupId, artifactId] = name.split(':');
74
+ for (const nodeGroup of [dependencyNodes, dependencyManagementNodes]) {
75
+ const nodes = nodeGroup.reduce((collection, node) => {
76
+ const dependencyNode = parseDependencyNode(node);
77
+ if (dependencyNode.groupId === groupId &&
78
+ dependencyNode.artifactId === artifactId &&
79
+ dependencyNode.version !== version.toString() &&
80
+ dependencyNode.versionNode) {
81
+ collection.push(dependencyNode.versionNode);
82
+ }
83
+ return collection;
84
+ }, []);
85
+ if (nodes.length) {
86
+ updates.push({
87
+ name,
88
+ nodes,
89
+ version,
90
+ });
91
+ }
92
+ }
93
+ }
94
+ return updates;
44
95
  }
45
96
  static updateNodes(nodes, value) {
46
97
  const toUpdate = nodes.filter(node => node.textContent !== value);
@@ -49,4 +100,36 @@ class PomXml extends base_xml_1.BaseXml {
49
100
  }
50
101
  }
51
102
  exports.PomXml = PomXml;
103
+ function parseDependencyNode(node) {
104
+ var _a, _b, _c, _d;
105
+ let groupId = '';
106
+ let artifactId = '';
107
+ let scope;
108
+ let version;
109
+ let versionNode;
110
+ for (let i = 0; i < node.childNodes.length; i++) {
111
+ const childNode = node.childNodes.item(i);
112
+ if (childNode.nodeName === 'groupId') {
113
+ groupId = ((_a = childNode.firstChild) === null || _a === void 0 ? void 0 : _a.textContent) || '';
114
+ }
115
+ else if (childNode.nodeName === 'artifactId') {
116
+ artifactId = ((_b = childNode.firstChild) === null || _b === void 0 ? void 0 : _b.textContent) || '';
117
+ }
118
+ else if (childNode.nodeName === 'scope') {
119
+ scope = ((_c = childNode.firstChild) === null || _c === void 0 ? void 0 : _c.textContent) || '';
120
+ }
121
+ else if (childNode.nodeName === 'version') {
122
+ version = ((_d = childNode.firstChild) === null || _d === void 0 ? void 0 : _d.textContent) || '';
123
+ versionNode = childNode;
124
+ }
125
+ }
126
+ return {
127
+ groupId,
128
+ artifactId,
129
+ scope,
130
+ version,
131
+ versionNode,
132
+ };
133
+ }
134
+ exports.parseDependencyNode = parseDependencyNode;
52
135
  //# sourceMappingURL=pom-xml.js.map
@@ -15,7 +15,7 @@
15
15
  Object.defineProperty(exports, "__esModule", { value: true });
16
16
  exports.TagName = void 0;
17
17
  const version_1 = require("../version");
18
- const TAG_PATTERN = /^((?<component>.*)(?<separator>[^a-zA-Z]))?(?<v>v)?(?<version>\d+\.\d+\.\d+.*)$/;
18
+ const TAG_PATTERN = /^((?<component>.*)(?<separator>[^a-zA-Z0-9]))?(?<v>v)?(?<version>\d+\.\d+\.\d+.*)$/;
19
19
  const DEFAULT_SEPARATOR = '-';
20
20
  class TagName {
21
21
  constructor(version, component, separator = DEFAULT_SEPARATOR, includeV = true) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-please",
3
- "version": "13.16.6",
3
+ "version": "13.18.0",
4
4
  "description": "generate release PRs based on the conventionalcommits.org spec",
5
5
  "main": "./build/src/index.js",
6
6
  "bin": "./build/src/bin/release-please.js",
@@ -78,7 +78,7 @@
78
78
  "@xmldom/xmldom": "^0.8.2",
79
79
  "chalk": "^4.0.0",
80
80
  "code-suggester": "^3.0.0",
81
- "conventional-changelog-conventionalcommits": "^4.6.0",
81
+ "conventional-changelog-conventionalcommits": "^5.0.0",
82
82
  "conventional-changelog-writer": "^5.0.0",
83
83
  "conventional-commits-filter": "^2.0.2",
84
84
  "detect-indent": "^6.1.0",