release-please 13.4.10 → 13.4.13

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,29 @@
4
4
 
5
5
  [1]: https://www.npmjs.com/package/release-please?activeTab=versions
6
6
 
7
+ ### [13.4.13](https://github.com/googleapis/release-please/compare/v13.4.12...v13.4.13) (2022-02-28)
8
+
9
+
10
+ ### Bug Fixes
11
+
12
+ * handle failures during multiple release creation ([#1315](https://github.com/googleapis/release-please/issues/1315)) ([fc856ae](https://github.com/googleapis/release-please/commit/fc856aed1d95def38170eff6381829cd6d7d1e0b))
13
+
14
+ ### [13.4.12](https://github.com/googleapis/release-please/compare/v13.4.11...v13.4.12) (2022-02-22)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * address false-positive matches for autorelease branch naming ([#1311](https://github.com/googleapis/release-please/issues/1311)) ([c5e76dc](https://github.com/googleapis/release-please/commit/c5e76dc8202958ed5af0f3635188261b8845f561)), closes [#1310](https://github.com/googleapis/release-please/issues/1310)
20
+ * catch FileNotFound error when building changeset ([#1306](https://github.com/googleapis/release-please/issues/1306)) ([3944b17](https://github.com/googleapis/release-please/commit/3944b17f33500cecc63a1ff63db81cdbd50ce1a1))
21
+ * manifest config should allow overriding labels ([#1303](https://github.com/googleapis/release-please/issues/1303)) ([f4d0314](https://github.com/googleapis/release-please/commit/f4d0314d1a394389a233ba9e1383852f0875dcd1)), closes [#1302](https://github.com/googleapis/release-please/issues/1302)
22
+
23
+ ### [13.4.11](https://github.com/googleapis/release-please/compare/v13.4.10...v13.4.11) (2022-02-18)
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * introduce file cache to simplify fetching files including file mode ([#1280](https://github.com/googleapis/release-please/issues/1280)) ([d7280b7](https://github.com/googleapis/release-please/commit/d7280b7eac3056e28399a0b80ea26002f0dff1b4))
29
+
7
30
  ### [13.4.10](https://github.com/googleapis/release-please/compare/v13.4.9...v13.4.10) (2022-02-16)
8
31
 
9
32
 
package/README.md CHANGED
@@ -109,6 +109,16 @@ END_COMMIT_OVERRIDE
109
109
  The next time release please runs, it will use that override section as the
110
110
  commit message instead of the merged commit message.
111
111
 
112
+ ## Release Please bot does not create a release PR. Why?
113
+
114
+ Release Please creates a release pull request after it sees the default branch
115
+ contains "releaseable units" since the last release.
116
+ A releasable unit is a commit to the branch with one of the following
117
+ prefixes: "feat" and "fix". (A "chore" commit is not a releasable unit.)
118
+
119
+ Some languages have their specific releasable unit configuration. For example,
120
+ "docs" is a prefix for releasable units in Java and Python.
121
+
112
122
  ## Strategy (Language) types supported
113
123
 
114
124
  Release Please automates releases for the following flavors of repositories:
@@ -29,4 +29,8 @@ export declare class DuplicateReleaseError extends GitHubAPIError {
29
29
  tag: string;
30
30
  constructor(requestError: RequestError, tag: string);
31
31
  }
32
+ export declare class FileNotFoundError extends Error {
33
+ path: string;
34
+ constructor(path: string);
35
+ }
32
36
  export {};
@@ -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.DuplicateReleaseError = exports.AuthError = exports.GitHubAPIError = exports.MissingRequiredFileError = exports.ConfigurationError = void 0;
16
+ exports.FileNotFoundError = exports.DuplicateReleaseError = exports.AuthError = exports.GitHubAPIError = exports.MissingRequiredFileError = exports.ConfigurationError = void 0;
17
17
  class ConfigurationError extends Error {
18
18
  constructor(message, releaserName, repository) {
19
19
  super(`${releaserName} (${repository}): ${message}`);
@@ -38,6 +38,7 @@ class GitHubAPIError extends Error {
38
38
  this.body = GitHubAPIError.parseErrorBody(requestError);
39
39
  this.name = GitHubAPIError.name;
40
40
  this.cause = requestError;
41
+ this.stack = requestError.stack;
41
42
  }
42
43
  static parseErrorBody(requestError) {
43
44
  const body = requestError.response;
@@ -65,4 +66,12 @@ class DuplicateReleaseError extends GitHubAPIError {
65
66
  }
66
67
  }
67
68
  exports.DuplicateReleaseError = DuplicateReleaseError;
69
+ class FileNotFoundError extends Error {
70
+ constructor(path) {
71
+ super(`Failed to find file: ${path}`);
72
+ this.path = path;
73
+ this.name = FileNotFoundError.name;
74
+ }
75
+ }
76
+ exports.FileNotFoundError = FileNotFoundError;
68
77
  //# sourceMappingURL=index.js.map
@@ -9,6 +9,7 @@ import { Repository } from './repository';
9
9
  import { ReleasePullRequest } from './release-pull-request';
10
10
  import { Update } from './update';
11
11
  import { Release } from './release';
12
+ import { GitHubFileContents } from './util/file-cache';
12
13
  declare type RequestBuilderType = typeof request;
13
14
  declare type DefaultFunctionType = RequestBuilderType['defaults'];
14
15
  declare type RequestFunctionType = ReturnType<DefaultFunctionType>;
@@ -30,11 +31,6 @@ interface GitHubCreateOptions {
30
31
  octokitAPIs?: OctokitAPIs;
31
32
  token?: string;
32
33
  }
33
- export interface GitHubFileContents {
34
- sha: string;
35
- content: string;
36
- parsedContent: string;
37
- }
38
34
  declare type CommitFilter = (commit: Commit) => boolean;
39
35
  interface CommitIteratorOptions {
40
36
  maxResults?: number;
@@ -68,6 +64,7 @@ export declare class GitHub {
68
64
  private octokit;
69
65
  private request;
70
66
  private graphql;
67
+ private fileCache;
71
68
  private constructor();
72
69
  /**
73
70
  * Build a new GitHub client with auto-detected default branch.
@@ -185,24 +182,6 @@ export declare class GitHub {
185
182
  * @throws {GitHubAPIError} on other API errors
186
183
  */
187
184
  getFileContents(path: string): Promise<GitHubFileContents>;
188
- /**
189
- * Fetch the contents of a file with the Contents API
190
- *
191
- * @param {string} path The path to the file in the repository
192
- * @param {string} branch The branch to fetch from
193
- * @returns {GitHubFileContents}
194
- * @throws {GitHubAPIError} on other API errors
195
- */
196
- getFileContentsWithSimpleAPI: (path: string, ref: string, isBranch?: any) => Promise<GitHubFileContents>;
197
- /**
198
- * Fetch the contents of a file using the Git data API
199
- *
200
- * @param {string} path The path to the file in the repository
201
- * @param {string} branch The branch to fetch from
202
- * @returns {GitHubFileContents}
203
- * @throws {GitHubAPIError} on other API errors
204
- */
205
- getFileContentsWithDataAPI: (path: string, branch: string) => Promise<GitHubFileContents>;
206
185
  /**
207
186
  * Fetch the contents of a file
208
187
  *
@@ -26,6 +26,7 @@ exports.GH_GRAPHQL_URL = 'https://api.github.com';
26
26
  const logger_1 = require("./util/logger");
27
27
  const manifest_1 = require("./manifest");
28
28
  const signoff_commit_message_1 = require("./util/signoff-commit-message");
29
+ const file_cache_1 = require("./util/file-cache");
29
30
  class GitHub {
30
31
  constructor(options) {
31
32
  /**
@@ -70,58 +71,6 @@ class GitHub {
70
71
  maxRetries -= 1;
71
72
  }
72
73
  });
73
- /**
74
- * Fetch the contents of a file with the Contents API
75
- *
76
- * @param {string} path The path to the file in the repository
77
- * @param {string} branch The branch to fetch from
78
- * @returns {GitHubFileContents}
79
- * @throws {GitHubAPIError} on other API errors
80
- */
81
- this.getFileContentsWithSimpleAPI = wrapAsync(async (path, ref, isBranch = true) => {
82
- ref = isBranch ? fullyQualifyBranchRef(ref) : ref;
83
- const options = {
84
- owner: this.repository.owner,
85
- repo: this.repository.repo,
86
- path,
87
- ref,
88
- };
89
- const resp = await this.request('GET /repos/:owner/:repo/contents/:path', options);
90
- return {
91
- parsedContent: Buffer.from(resp.data.content, 'base64').toString('utf8'),
92
- content: resp.data.content,
93
- sha: resp.data.sha,
94
- };
95
- });
96
- /**
97
- * Fetch the contents of a file using the Git data API
98
- *
99
- * @param {string} path The path to the file in the repository
100
- * @param {string} branch The branch to fetch from
101
- * @returns {GitHubFileContents}
102
- * @throws {GitHubAPIError} on other API errors
103
- */
104
- this.getFileContentsWithDataAPI = wrapAsync(async (path, branch) => {
105
- const repoTree = await this.octokit.git.getTree({
106
- owner: this.repository.owner,
107
- repo: this.repository.repo,
108
- tree_sha: branch,
109
- });
110
- const blobDescriptor = repoTree.data.tree.find(tree => tree.path === path);
111
- if (!blobDescriptor) {
112
- throw new Error(`Could not find requested path: ${path}`);
113
- }
114
- const resp = await this.octokit.git.getBlob({
115
- owner: this.repository.owner,
116
- repo: this.repository.repo,
117
- file_sha: blobDescriptor.sha,
118
- });
119
- return {
120
- parsedContent: Buffer.from(resp.data.content, 'base64').toString('utf8'),
121
- content: resp.data.content,
122
- sha: resp.data.sha,
123
- };
124
- });
125
74
  /**
126
75
  * Returns a list of paths to all files with a given name.
127
76
  *
@@ -399,6 +348,7 @@ class GitHub {
399
348
  this.octokit = options.octokitAPIs.octokit;
400
349
  this.request = options.octokitAPIs.request;
401
350
  this.graphql = options.octokitAPIs.graphql;
351
+ this.fileCache = new file_cache_1.RepositoryFileCache(this.octokit, this.repository);
402
352
  }
403
353
  /**
404
354
  * Build a new GitHub client with auto-detected default branch.
@@ -871,15 +821,7 @@ class GitHub {
871
821
  */
872
822
  async getFileContentsOnBranch(path, branch) {
873
823
  logger_1.logger.debug(`Fetching ${path} from branch ${branch}`);
874
- try {
875
- return await this.getFileContentsWithSimpleAPI(path, branch);
876
- }
877
- catch (err) {
878
- if (err.status === 403) {
879
- return await this.getFileContentsWithDataAPI(path, branch);
880
- }
881
- throw err;
882
- }
824
+ return await this.fileCache.getFileContents(path, branch);
883
825
  }
884
826
  async getFileJson(path, branch) {
885
827
  const content = await this.getFileContentsOnBranch(path, branch);
@@ -938,18 +880,10 @@ class GitHub {
938
880
  for (const update of updates) {
939
881
  let content;
940
882
  try {
941
- if (update.cachedFileContents) {
942
- // we already loaded the file contents earlier, let's not
943
- // hit GitHub again.
944
- content = { data: update.cachedFileContents };
945
- }
946
- else {
947
- const fileContent = await this.getFileContentsOnBranch(update.path, defaultBranch);
948
- content = { data: fileContent };
949
- }
883
+ content = await this.getFileContentsOnBranch(update.path, defaultBranch);
950
884
  }
951
885
  catch (err) {
952
- if (err.status !== 404)
886
+ if (!(err instanceof errors_1.FileNotFoundError))
953
887
  throw err;
954
888
  // if the file is missing and create = false, just continue
955
889
  // to the next update, otherwise create the file.
@@ -959,13 +893,13 @@ class GitHub {
959
893
  }
960
894
  }
961
895
  const contentText = content
962
- ? Buffer.from(content.data.content, 'base64').toString('utf8')
896
+ ? Buffer.from(content.content, 'base64').toString('utf8')
963
897
  : undefined;
964
898
  const updatedContent = update.updater.updateContent(contentText);
965
899
  if (updatedContent) {
966
900
  changes.set(update.path, {
967
901
  content: updatedContent,
968
- mode: '100644',
902
+ mode: (content === null || content === void 0 ? void 0 : content.mode) || file_cache_1.DEFAULT_FILE_MODE,
969
903
  });
970
904
  }
971
905
  }
@@ -1005,17 +939,6 @@ class GitHub {
1005
939
  }
1006
940
  }
1007
941
  exports.GitHub = GitHub;
1008
- // Takes a potentially unqualified branch name, and turns it
1009
- // into a fully qualified ref.
1010
- //
1011
- // e.g. main -> refs/heads/main
1012
- function fullyQualifyBranchRef(refName) {
1013
- let final = refName;
1014
- if (final.indexOf('/') < 0) {
1015
- final = `refs/heads/${final}`;
1016
- }
1017
- return final;
1018
- }
1019
942
  /**
1020
943
  * Normalize a provided prefix by removing leading and trailing
1021
944
  * slashes.
@@ -24,6 +24,7 @@ const factory_1 = require("./factory");
24
24
  const pull_request_body_1 = require("./util/pull-request-body");
25
25
  const merge_1 = require("./plugins/merge");
26
26
  const release_please_manifest_1 = require("./updaters/release-please-manifest");
27
+ const errors_1 = require("./errors");
27
28
  exports.DEFAULT_RELEASE_PLEASE_CONFIG = 'release-please-config.json';
28
29
  exports.DEFAULT_RELEASE_PLEASE_MANIFEST = '.release-please-manifest.json';
29
30
  exports.ROOT_PROJECT_PATH = '.';
@@ -525,7 +526,25 @@ class Manifest {
525
526
  for (const release of releases) {
526
527
  promises.push(this.createRelease(release));
527
528
  }
528
- const githubReleases = await Promise.all(promises);
529
+ const duplicateReleases = [];
530
+ const githubReleases = [];
531
+ for (const promise of promises) {
532
+ try {
533
+ githubReleases.push(await promise);
534
+ }
535
+ catch (err) {
536
+ if (err instanceof errors_1.DuplicateReleaseError) {
537
+ logger_1.logger.warn(`Duplicate release tag: ${err.tag}`);
538
+ duplicateReleases.push(err);
539
+ }
540
+ else {
541
+ throw err;
542
+ }
543
+ }
544
+ }
545
+ if (duplicateReleases.length > 0 && githubReleases.length === 0) {
546
+ throw duplicateReleases[0];
547
+ }
529
548
  // adjust tags on pullRequest
530
549
  await Promise.all([
531
550
  this.github.removeIssueLabels(this.labels, pullRequest.number),
@@ -629,6 +648,8 @@ async function parseConfig(github, configFile, branch) {
629
648
  for (const path in config.packages) {
630
649
  repositoryConfig[path] = mergeReleaserConfig(defaultConfig, extractReleaserConfig(config.packages[path]));
631
650
  }
651
+ const configLabel = config['label'];
652
+ const configReleaseLabel = config['release-label'];
632
653
  const manifestOptions = {
633
654
  bootstrapSha: config['bootstrap-sha'],
634
655
  lastReleaseSha: config['last-release-sha'],
@@ -636,6 +657,8 @@ async function parseConfig(github, configFile, branch) {
636
657
  separatePullRequests: config['separate-pull-requests'],
637
658
  groupPullRequestTitlePattern: config['group-pull-request-title-pattern'],
638
659
  plugins: config['plugins'],
660
+ labels: configLabel === undefined ? undefined : [configLabel],
661
+ releaseLabels: configReleaseLabel === undefined ? undefined : [configReleaseLabel],
639
662
  };
640
663
  return { config: repositoryConfig, options: manifestOptions };
641
664
  }
@@ -1,7 +1,7 @@
1
1
  import { Update } from '../update';
2
2
  import { Version, VersionsMap } from '../version';
3
3
  import { BaseStrategy, BuildUpdatesOptions, BaseStrategyOptions } from './base';
4
- import { GitHubFileContents } from '../github';
4
+ import { GitHubFileContents } from '../util/file-cache';
5
5
  import { Commit, ConventionalCommit } from '../commit';
6
6
  import { Release } from '../release';
7
7
  import { ReleasePullRequest } from '../release-pull-request';
@@ -1,4 +1,4 @@
1
- import { GitHubFileContents } from './github';
1
+ import { GitHubFileContents } from './util/file-cache';
2
2
  /**
3
3
  * An update is a collection of data that represents changes to
4
4
  * a file in a repository.
@@ -82,8 +82,12 @@ exports.BranchName = BranchName;
82
82
  * @see https://github.com/googleapis/releasetool
83
83
  */
84
84
  const AUTORELEASE_PATTERN = /^release-?(?<component>[\w-.]*)?-v(?<version>[0-9].*)$/;
85
+ const RELEASE_PLEASE_BRANCH_PREFIX = 'release-please--branches';
85
86
  class AutoreleaseBranchName extends BranchName {
86
87
  static matches(branchName) {
88
+ if (branchName.startsWith(RELEASE_PLEASE_BRANCH_PREFIX)) {
89
+ return false;
90
+ }
87
91
  return !!branchName.match(AUTORELEASE_PATTERN);
88
92
  }
89
93
  constructor(branchName) {
@@ -0,0 +1,104 @@
1
+ import { Octokit } from '@octokit/rest';
2
+ import { Repository } from '../repository';
3
+ export declare const DEFAULT_FILE_MODE = "100644";
4
+ export interface GitHubFileContents {
5
+ sha: string;
6
+ content: string;
7
+ parsedContent: string;
8
+ mode: string;
9
+ }
10
+ /**
11
+ * This class is a read-through cache aimed at minimizing the
12
+ * number of API requests needed to fetch file data/contents.
13
+ * It lazy-caches data as it reads and will return cached data
14
+ * for resources already fetched.
15
+ */
16
+ export declare class RepositoryFileCache {
17
+ private octokit;
18
+ private repository;
19
+ private cache;
20
+ /**
21
+ * Instantiate a new loading cache instance
22
+ *
23
+ * @param {Octokit} octokit An authenticated octokit instance
24
+ * @param {Repository} repository The repository we are fetching data for
25
+ */
26
+ constructor(octokit: Octokit, repository: Repository);
27
+ /**
28
+ * Fetch file contents for given path on a given branch. If the
29
+ * data has already been fetched, return a cached copy.
30
+ *
31
+ * @param {string} path Path to the file
32
+ * @param {string} branch Branch to fetch the file from
33
+ * @returns {GitHubFileContents} The file contents
34
+ */
35
+ getFileContents(path: string, branch: string): Promise<GitHubFileContents>;
36
+ }
37
+ /**
38
+ * This class is a read-through cache for a single branch aimed
39
+ * at minimizing the number of API requests needed to fetch file
40
+ * data/contents. It lazy-caches data as it reads and will return
41
+ * cached data for resources already fetched.
42
+ */
43
+ export declare class BranchFileCache {
44
+ private octokit;
45
+ private repository;
46
+ private branch;
47
+ private cache;
48
+ private treeCache;
49
+ private treeEntries?;
50
+ /**
51
+ * Instantiate a new loading cache instance
52
+ *
53
+ * @param {Octokit} octokit An authenticated octokit instance
54
+ * @param {Repository} repository The repository we are fetching data for
55
+ * @param {string} branch The branch we are fetching data from
56
+ */
57
+ constructor(octokit: Octokit, repository: Repository, branch: string);
58
+ /**
59
+ * Fetch file contents for given path. If the data has already been
60
+ * fetched, return the cached copy.
61
+ *
62
+ * @param {string} path Path to the file
63
+ * @param {string} branch Branch to fetch the file from
64
+ * @returns {GitHubFileContents} The file contents
65
+ */
66
+ getFileContents(path: string): Promise<GitHubFileContents>;
67
+ /**
68
+ * Actually fetch the file contents. Uses the tree API to fetch file
69
+ * data.
70
+ *
71
+ * @param {string} path Path to the file
72
+ */
73
+ private fetchFileContents;
74
+ /**
75
+ * Return the full recursive git tree. If already fetched, return
76
+ * the cached version. If the tree is too big, return null.
77
+ *
78
+ * @returns {TreeEntry[]} The tree entries
79
+ */
80
+ private getFullTree;
81
+ /**
82
+ * Returns the git tree for a given SHA. If already fetched, return
83
+ * the cached version.
84
+ *
85
+ * @param {string} sha The tree SHA
86
+ * @returns {TreeEntry[]} The tree entries
87
+ */
88
+ private getTree;
89
+ /**
90
+ * Fetch the git tree via the GitHub API
91
+ *
92
+ * @param {string} sha The tree SHA
93
+ * @returns {TreeEntry[]} The tree entries
94
+ */
95
+ private fetchTree;
96
+ /**
97
+ * Fetch the git blob from the GitHub API and convert into a
98
+ * GitHubFileContents object.
99
+ *
100
+ * @param {string} blobSha The git blob SHA
101
+ * @param {TreeEntry} treeEntry The associated tree object
102
+ */
103
+ private fetchContents;
104
+ }
@@ -0,0 +1,206 @@
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.BranchFileCache = exports.RepositoryFileCache = exports.DEFAULT_FILE_MODE = void 0;
17
+ const logger_1 = require("./logger");
18
+ const errors_1 = require("../errors");
19
+ exports.DEFAULT_FILE_MODE = '100644';
20
+ /**
21
+ * This class is a read-through cache aimed at minimizing the
22
+ * number of API requests needed to fetch file data/contents.
23
+ * It lazy-caches data as it reads and will return cached data
24
+ * for resources already fetched.
25
+ */
26
+ class RepositoryFileCache {
27
+ /**
28
+ * Instantiate a new loading cache instance
29
+ *
30
+ * @param {Octokit} octokit An authenticated octokit instance
31
+ * @param {Repository} repository The repository we are fetching data for
32
+ */
33
+ constructor(octokit, repository) {
34
+ this.octokit = octokit;
35
+ this.repository = repository;
36
+ this.cache = new Map();
37
+ }
38
+ /**
39
+ * Fetch file contents for given path on a given branch. If the
40
+ * data has already been fetched, return a cached copy.
41
+ *
42
+ * @param {string} path Path to the file
43
+ * @param {string} branch Branch to fetch the file from
44
+ * @returns {GitHubFileContents} The file contents
45
+ */
46
+ async getFileContents(path, branch) {
47
+ let fileCache = this.cache.get(branch);
48
+ if (!fileCache) {
49
+ fileCache = new BranchFileCache(this.octokit, this.repository, branch);
50
+ this.cache.set(branch, fileCache);
51
+ }
52
+ return await fileCache.getFileContents(path);
53
+ }
54
+ }
55
+ exports.RepositoryFileCache = RepositoryFileCache;
56
+ /**
57
+ * This class is a read-through cache for a single branch aimed
58
+ * at minimizing the number of API requests needed to fetch file
59
+ * data/contents. It lazy-caches data as it reads and will return
60
+ * cached data for resources already fetched.
61
+ */
62
+ class BranchFileCache {
63
+ /**
64
+ * Instantiate a new loading cache instance
65
+ *
66
+ * @param {Octokit} octokit An authenticated octokit instance
67
+ * @param {Repository} repository The repository we are fetching data for
68
+ * @param {string} branch The branch we are fetching data from
69
+ */
70
+ constructor(octokit, repository, branch) {
71
+ this.octokit = octokit;
72
+ this.repository = repository;
73
+ this.branch = branch;
74
+ this.cache = new Map();
75
+ this.treeCache = new Map();
76
+ }
77
+ /**
78
+ * Fetch file contents for given path. If the data has already been
79
+ * fetched, return the cached copy.
80
+ *
81
+ * @param {string} path Path to the file
82
+ * @param {string} branch Branch to fetch the file from
83
+ * @returns {GitHubFileContents} The file contents
84
+ */
85
+ async getFileContents(path) {
86
+ const cached = this.cache.get(path);
87
+ if (cached) {
88
+ return cached;
89
+ }
90
+ const fetched = await this.fetchFileContents(path);
91
+ this.cache.set(path, fetched);
92
+ return fetched;
93
+ }
94
+ /**
95
+ * Actually fetch the file contents. Uses the tree API to fetch file
96
+ * data.
97
+ *
98
+ * @param {string} path Path to the file
99
+ */
100
+ async fetchFileContents(path) {
101
+ // try to use the entire git tree if it's not too big
102
+ const treeEntries = await this.getFullTree();
103
+ if (treeEntries) {
104
+ logger_1.logger.debug(`Using full tree to find ${path}`);
105
+ const found = treeEntries.find(entry => entry.path === path);
106
+ if (found === null || found === void 0 ? void 0 : found.sha) {
107
+ return await this.fetchContents(found.sha, found);
108
+ }
109
+ throw new errors_1.FileNotFoundError(path);
110
+ }
111
+ // full tree is too big, use data API to fetch
112
+ const parts = path.split('/');
113
+ let treeSha = this.branch;
114
+ let found;
115
+ for (const part of parts) {
116
+ const tree = await this.getTree(treeSha);
117
+ found = tree.find(item => item.path === part);
118
+ if (!(found === null || found === void 0 ? void 0 : found.sha)) {
119
+ throw new errors_1.FileNotFoundError(path);
120
+ }
121
+ treeSha = found.sha;
122
+ }
123
+ if (found === null || found === void 0 ? void 0 : found.sha) {
124
+ return await this.fetchContents(found.sha, found);
125
+ }
126
+ throw new errors_1.FileNotFoundError(path);
127
+ }
128
+ /**
129
+ * Return the full recursive git tree. If already fetched, return
130
+ * the cached version. If the tree is too big, return null.
131
+ *
132
+ * @returns {TreeEntry[]} The tree entries
133
+ */
134
+ async getFullTree() {
135
+ if (this.treeEntries === undefined) {
136
+ // fetch all tree entries recursively
137
+ const { data: { tree, truncated }, } = await this.octokit.git.getTree({
138
+ owner: this.repository.owner,
139
+ repo: this.repository.repo,
140
+ tree_sha: this.branch,
141
+ recursive: 'true',
142
+ });
143
+ if (truncated) {
144
+ // the full tree is too big to use, mark it as unusable
145
+ this.treeEntries = null;
146
+ }
147
+ else {
148
+ this.treeEntries = tree;
149
+ }
150
+ }
151
+ return this.treeEntries;
152
+ }
153
+ /**
154
+ * Returns the git tree for a given SHA. If already fetched, return
155
+ * the cached version.
156
+ *
157
+ * @param {string} sha The tree SHA
158
+ * @returns {TreeEntry[]} The tree entries
159
+ */
160
+ async getTree(sha) {
161
+ const cached = this.treeCache.get(sha);
162
+ if (cached) {
163
+ return cached;
164
+ }
165
+ const fetched = await this.fetchTree(sha);
166
+ this.treeCache.set(sha, fetched);
167
+ return fetched;
168
+ }
169
+ /**
170
+ * Fetch the git tree via the GitHub API
171
+ *
172
+ * @param {string} sha The tree SHA
173
+ * @returns {TreeEntry[]} The tree entries
174
+ */
175
+ async fetchTree(sha) {
176
+ const { data: { tree }, } = await this.octokit.git.getTree({
177
+ owner: this.repository.owner,
178
+ repo: this.repository.repo,
179
+ tree_sha: sha,
180
+ recursive: 'false',
181
+ });
182
+ return tree;
183
+ }
184
+ /**
185
+ * Fetch the git blob from the GitHub API and convert into a
186
+ * GitHubFileContents object.
187
+ *
188
+ * @param {string} blobSha The git blob SHA
189
+ * @param {TreeEntry} treeEntry The associated tree object
190
+ */
191
+ async fetchContents(blobSha, treeEntry) {
192
+ const { data: { content }, } = await this.octokit.git.getBlob({
193
+ owner: this.repository.owner,
194
+ repo: this.repository.repo,
195
+ file_sha: blobSha,
196
+ });
197
+ return {
198
+ sha: blobSha,
199
+ mode: treeEntry.mode || exports.DEFAULT_FILE_MODE,
200
+ content,
201
+ parsedContent: Buffer.from(content, 'base64').toString('utf8'),
202
+ };
203
+ }
204
+ }
205
+ exports.BranchFileCache = BranchFileCache;
206
+ //# sourceMappingURL=file-cache.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "release-please",
3
- "version": "13.4.10",
3
+ "version": "13.4.13",
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",