diff --git a/doc/lib/command/doc.py b/doc/lib/command/doc.py index 9e4666a7b..b51b39d9a 100644 --- a/doc/lib/command/doc.py +++ b/doc/lib/command/doc.py @@ -181,7 +181,7 @@ def _build(config, var_store): var_store.add("release-date", date) var_store.add("release-year", year) - release_history_update(path_repo, config.doc_path) + claim = release_history_update(path_repo, config.doc_path) document_map = { "command": reference_command_render(bld_cfg, bld_hlp), @@ -189,7 +189,7 @@ def _build(config, var_store): "index": news_index_render(index, news), "news": news_render(news), "user-guide": build_pre(user_guide, bld_hlp, var_store), - "release": release_render(release, config.doc_path, config.var_map.get("dev") == "y"), + "release": release_render(release, config.doc_path, config.var_map.get("dev") == "y", claim), } return document_map, reference_man_render(index, bld_cfg, bld_hlp) diff --git a/doc/lib/command/render/release.py b/doc/lib/command/render/release.py index 4bec882a4..d1f1a67ec 100644 --- a/doc/lib/command/render/release.py +++ b/doc/lib/command/render/release.py @@ -15,7 +15,7 @@ from collections import deque from common.date import date_render from common.error import ToolError -from common.exec import exec_result +from common.exec import exec_result, exec_status from common.storage import file_read, file_write from common.xml import ( xml_document_new, @@ -35,6 +35,9 @@ from config.project import PROJECT_NAME # Where the git history is cached _FILE_HISTORY = "resource/git-history.cache" +# Local branch the git history ends at when it is related to HEAD +_HISTORY_BRANCH = "refs/heads/integration" + # Subject of a commit that closed a release _RELEASE_SUBJECT_EXP = re.compile(r"^v[0-9]{1,2}\.[0-9]{1,2}(\.[0-9]+)?: ") @@ -57,6 +60,7 @@ _ITEM_LIST = ( _CONTRIBUTOR_LIST = ( ("release-item-contributor", "Fixed", "Contributed"), ("release-item-reviewer", "Reviewed", "Reviewed"), + ("release-item-tester", "Tested", "Tested"), ("release-item-ideator", "Reported", "Suggested"), ) @@ -71,7 +75,7 @@ _COMMIT_URL = "{[github-url-base]}/commit/%s" _COMMIT_SIZE = 7 # Releases with version >= this have the paragraphs after the first and the links of an item in details -_DETAIL_VERSION_MIN = "2.60" +_DETAIL_VERSION_MIN = "2.33" # A bug fix release is x.y.z with z > 0 _VERSION_BUG_FIX_EXP = re.compile(r"^[0-9]+\.[0-9]+\.[1-9][0-9]*$") @@ -105,22 +109,57 @@ def release_current_stable(root): #################################################################################################################################### def release_history_update(path_repo, path_doc): - """Write the git history the release notes are checked against when HEAD is not the newest commit in it. + """Write the git history the release notes are checked against when the newest commit in it has changed. - The body of a commit that closed a release is left out.""" + When the local integration branch is related to HEAD the history ends at the newest commit of HEAD that is also in integration + and the result is true. The commits of a release branch are left out this way. Otherwise the history ends at HEAD and the result + is false. The body of a commit that closed a release is left out.""" path_history = os.path.join(path_doc, _FILE_HISTORY) - head = exec_result("git -C %s rev-parse HEAD" % path_repo, suppress_stderr=True)[1].strip() + command = "git -C %s merge-base HEAD %s" % (path_repo, _HISTORY_BRANCH) + related = exec_status(command) == 0 + head = exec_result(command if related else "git -C %s rev-parse HEAD" % path_repo, suppress_stderr=True)[1].strip() - if os.path.isfile(path_history) and json.loads(file_read(path_history))[0]["commit"] == head: - return + # The tag of each patch release with version >= _DETAIL_VERSION_MIN + tag_map = {} + + for tag in exec_result("git -C %s tag --list 'release/*'" % path_repo, suppress_stderr=True)[1].split(): + version = tag[len("release/") :] + + if _VERSION_BUG_FIX_EXP.match(version) is not None and version >= _DETAIL_VERSION_MIN: + tag_map[version] = exec_result("git -C %s rev-parse '%s^{commit}'" % (path_repo, tag), suppress_stderr=True)[1].strip() + + if os.path.isfile(path_history): + history = json.loads(file_read(path_history)) + + if ( + isinstance(history, dict) + and history["head"][0]["commit"] == head + and {version: tag_list[0]["commit"] for version, tag_list in history["tag"].items()} == tag_map + ): + return related + + # The history of a patch release is the commits of its tag that are not in the history of HEAD + history = { + "head": _history_read(path_repo, head), + "tag": {version: _history_read(path_repo, "%s --not %s" % (commit, head)) for version, commit in tag_map.items()}, + } + + file_write(path_history, json.dumps(history, indent=4, ensure_ascii=False) + "\n") + + return related + + +#################################################################################################################################### +def _history_read(path_repo, revision): + """Read the commits git log lists for a revision, newest first.""" # Records are separated by a byte that cannot appear in a commit message, and so are the fields within a record output = exec_result( - "git -C %s log --pretty=format:%%H%%x00%%ci%%x00%%s%%x00%%b%%x1e %s" % (path_repo, head), suppress_stderr=True + "git -C %s log --pretty=format:%%H%%x00%%ci%%x00%%s%%x00%%b%%x1e %s" % (path_repo, revision), suppress_stderr=True )[1] - history = [] + result = [] for record in output.split("\x1e"): record = record.strip("\n") @@ -135,9 +174,9 @@ def release_history_update(path_repo, path_doc): if body != "" and _RELEASE_SUBJECT_EXP.match(subject) is None: entry["body"] = body - history.append(entry) + result.append(entry) - file_write(path_history, json.dumps(history, indent=4, ensure_ascii=False) + "\n") + return result #################################################################################################################################### @@ -157,11 +196,15 @@ def _date_render(date, version): class _Release: """Builds the release document.""" - def __init__(self, root, path_doc, dev): + def __init__(self, root, path_doc, dev, claim): self.root = root self.dev = dev + self.claim = claim # Must every commit of a release be claimed by an item? + self.version_list = [xml_node_attribute(release, "version", True) for release in release_list(root)] - self.history = deque(json.loads(file_read(os.path.join(path_doc, _FILE_HISTORY)))) + history = json.loads(file_read(os.path.join(path_doc, _FILE_HISTORY))) + self.history = deque(history["head"]) + self.history_tag = history["tag"] # The first contributor is the default for every item, which is what keeps the common case out of the xml self.contributor_map = {} @@ -179,6 +222,9 @@ class _Release: self.render = DocRender("text") self.render.tag_set("backrest", PROJECT_NAME) + # The items of each release that are not development items, as [text, list item, item, commits, development items] + self.release_item_map = {} + ################################################################################################################################ def _contributor_text(self, item, item_type): """What the release notes say about who did the work on an item.""" @@ -239,17 +285,19 @@ class _Release: return result ################################################################################################################################ - def _commit_find(self, commit_list, subject, regexp=True): - """Find a commit by what its subject begins with, which is how a release item is tied to the work that did it.""" + def _commit_find(self, commit_list, subject, regexp=True, key="subject"): + """Find a commit by what its subject begins with, which is how a release item is tied to the work that did it. + + With key="commit" the commit is found by what its hash begins with.""" result = None for commit in commit_list: - found = re.match(subject, commit["subject"]) is not None if regexp else commit["subject"].startswith(subject) + found = re.match(subject, commit[key]) is not None if regexp else commit[key].startswith(subject) if found: if result is not None: - raise ToolError("subject prefix '%s' already found in commit %s" % (subject, commit["commit"])) + raise ToolError("%s prefix '%s' already found in commit %s" % (key, subject, commit["commit"])) result = commit @@ -274,24 +322,35 @@ class _Release: def _commit_list(self, version, release_idx, release_all): """Every commit that belongs to a release, and whether the items of the release are checked against them. - A bug fix release that is not the most recent is skipped since it was built on a branch of its own, so the commits are not - in the history between this release and the one before it.""" + A bug fix release that is not the most recent was built on a branch of its own, so its commits are read from the history of + its tag. It is skipped when there is no history for its tag.""" - if version < "2.01" or (_VERSION_BUG_FIX_EXP.match(version) is not None and release_idx != 0): + bug_fix = _VERSION_BUG_FIX_EXP.match(version) is not None and release_idx != 0 + + if version < "2.01" or (bug_fix and version not in self.history_tag): return [], [], {}, False + history = deque(self.history_tag[version]) if bug_fix else self.history dev = version.endswith("dev") # The commit that opened development on this release and the commit that closed the release before it, which are the ends of # what belongs to this release - commit_begin = self._commit_find(self.history, "Begin v%s development\\." % version) + commit_begin = self._commit_find(history, "Begin v%s development\\." % version) + + # Development on an x.y.0 release may have been opened as x.y + if commit_begin is None and version.endswith(".0"): + commit_begin = self._commit_find(history, "Begin v%s development\\." % version[:-2]) + commit_begin = None if commit_begin is None else commit_begin["commit"] - # Skip back over bug fix releases, which were built on branches of their own + # Skip back over bug fix releases, which were built on branches of their own. The tag history of a bug fix release ends + # at the release before it. last_idx = release_idx + 1 - while last_idx < len(release_all) and _VERSION_BUG_FIX_EXP.match( - xml_node_attribute(release_all[last_idx], "version", True) + while ( + not bug_fix + and last_idx < len(release_all) + and _VERSION_BUG_FIX_EXP.match(xml_node_attribute(release_all[last_idx], "version", True)) ): last_idx += 1 @@ -300,21 +359,21 @@ class _Release: version_last = xml_node_attribute(release_all[last_idx], "version", True) - commit_last_end = self._commit_find(self.history, "v%s\\: .+" % version_last) + commit_last_end = self._commit_find(history, "v%s\\: .+" % version_last) - if commit_last_end is None: + if commit_last_end is None and not bug_fix: raise ToolError("release %s must have an end commit" % version_last) # A release that is out has a commit that closed it, which the release after it has already checked for - commit_end = self._commit_find(self.history, "v%s\\: .+" % version) + commit_end = self._commit_find(history, "v%s\\: .+" % version) commit_end = None if commit_end is None else commit_end["commit"] commit_list = [] remaining_list = [] commit_map = {} - while len(self.history) > 0 and self.history[0]["commit"] != commit_last_end["commit"]: - commit = self.history.popleft() + while len(history) > 0 and (commit_last_end is None or history[0]["commit"] != commit_last_end["commit"]): + commit = history.popleft() # The commits that open and close a release are the release rather than part of it if commit["commit"] in (commit_begin, commit_end): @@ -357,18 +416,32 @@ class _Release: for commit_xml in commit_xml_list: subject = xml_node_attribute(commit_xml, "subject", True) - commit = self._commit_find(commit_list, subject, False) + commit_id = xml_node_attribute(commit_xml, "id") - if commit is None: - if check: - self._commit_error( - "unable to find release %s commit subject '%s' in list" % (version, subject), remaining_list, commit_map + # A commit with an id is found by the id and its subject must begin with the subject named + if commit_id is not None: + name = "id '%s'" % commit_id + commit = self._commit_find(commit_list, commit_id, False, "commit") + + if commit is not None and not commit["subject"].startswith(subject): + raise ToolError( + "release %s commit id '%s' subject '%s' does not begin with '%s'" + % (version, commit_id, commit["subject"], subject) ) - elif commit["commit"] in remaining_list: - remaining_list.remove(commit["commit"]) + else: + name = "subject '%s'" % subject + commit = self._commit_find(commit_list, subject, False) + + if commit is None and check: + self._commit_error("unable to find release %s commit %s in list" % (version, name), remaining_list, commit_map) result.append((commit_xml, commit)) + # Remove the commits found from the commits no item has claimed + for _, commit in result: + if commit is not None and commit["commit"] in remaining_list: + remaining_list.remove(commit["commit"]) + return result ################################################################################################################################ @@ -396,26 +469,43 @@ class _Release: self._ref_add(ref, label, url % id, "#%s" % id) ################################################################################################################################ - def _detail_add(self, list_item, item, item_commit_list): - """Add the paragraphs after the first and the issues, pull requests, and commits of an item as details. + @staticmethod + def _version_line_add(detail, version, text, note=None): + """Add a line to details that links to a release, after the text of a release note in quotes when note is not None.""" + + ref_item = xml_node_add(xml_node_add(detail, "list-detail-ref"), "list-detail-ref-item") + + xml_node_content_add(ref_item, text) + + if note is not None: + xml_node_content_add(xml_node_add(ref_item, "quote"), note) + xml_node_content_add(ref_item, " in ") + + xml_node_content_add(xml_node_add(ref_item, "link", {"url": "#%s" % version}), "v%s" % version) + xml_node_content_add(ref_item, ":") + + ################################################################################################################################ + def _ref_line_add(self, detail, item, item_commit_list, commit_line): + """Add the issues, pull requests, and commits of an item to details. An item with one commit has the commit on the same line as its issues and pull requests, after them. An item with more than - one commit has a line for each commit, with the subject of the commit and the issues and pull requests the commit element - names.""" + one commit, or any item when commit_line is true, has a line for each commit, with the subject of the commit and the issues + and pull requests the commit element names. The issues and pull requests of an item with one commit are on the line of the + commit when commit_line is true.""" - detail = xml_node_add(list_item, "list-detail") - - for paragraph in xml_node_child_list(item, "p")[1:]: - xml_node_child_add(xml_node_add(detail, "list-detail-text"), paragraph) + item_line = commit_line and len(item_commit_list) == 1 + commit_line = commit_line or len(item_commit_list) > 1 ref = xml_node_add(detail, "list-detail-ref") - self._ref_list_add(ref, item) + + if not item_line: + self._ref_list_add(ref, item) for commit_xml, commit in item_commit_list: url = None if commit is None else _COMMIT_URL % commit["commit"] hash = None if commit is None else commit["commit"][:_COMMIT_SIZE] - if len(item_commit_list) > 1: + if commit_line: ref = xml_node_add(detail, "list-detail-ref") # Escape the subject for html @@ -425,9 +515,39 @@ class _Release: if commit_xml is not None: self._ref_list_add(ref, commit_xml) - if len(item_commit_list) == 1 and commit is not None: + if item_line: + self._ref_list_add(ref, item) + + if not commit_line and commit is not None: self._ref_add(ref, "Commit", url, hash, True) + ################################################################################################################################ + def _detail_add(self, list_item, item, item_commit_list, commit_line=False, release_note=None, dev_list=()): + """Add the paragraphs after the first and the issues, pull requests, and commits of an item as details. + + release_note is the version and text of the release note a development item names. dev_list is the development items + that name an item as their release note, as (version, item, commits), listed under a line for each release that links to + it.""" + + detail = xml_node_add(list_item, "list-detail") + + for paragraph in xml_node_child_list(item, "p")[1:]: + xml_node_child_add(xml_node_add(detail, "list-detail-text"), paragraph) + + if release_note is not None: + self._version_line_add(detail, release_note[0], "Development for ", release_note[1]) + + self._ref_line_add(detail, item, item_commit_list, commit_line) + + dev_version_last = None + + for dev_version, dev_item, dev_commit_list in dev_list: + if dev_version != dev_version_last: + self._version_line_add(detail, dev_version, "Development in ") + dev_version_last = dev_version + + self._ref_line_add(detail, dev_item, dev_commit_list, True) + # Remove lines with no links and details with nothing in them for ref in xml_node_child_list(detail, "list-detail-ref"): if len(ref) == 0: @@ -436,6 +556,49 @@ class _Release: if len(detail) == 0: list_item.remove(detail) + ################################################################################################################################ + def _release_note_add(self, item, version, item_commit_list): + """Add a development item to the details of the release note it names. A release note is an item that is not a development + item in a later release. Returns the version and the text without a period at the end of the release note, or None when the + item names no release note.""" + + release_note = xml_node_child(item, "release-note") + + if release_note is None: + return None + + note_version = xml_node_attribute(release_note, "version", True) + note_subject = xml_node_attribute(release_note, "subject", True) + + # A release in development is named by the version it will have when it is released + if note_version not in self.version_list and note_version + "dev" in self.version_list: + note_version += "dev" + + if note_version not in self.version_list or self.version_list.index(note_version) >= self.version_list.index(version): + raise ToolError("release %s release note version %s is not a later release" % (version, note_version)) + + note_list = [note for note in self.release_item_map.get(note_version, []) if note[0].startswith(note_subject)] + + if len(note_list) == 0: + raise ToolError("release %s release note '%s' not found in release %s" % (version, note_subject, note_version)) + + if len(note_list) > 1: + raise ToolError( + "release %s release note '%s' found more than once in release %s" % (version, note_subject, note_version) + ) + + note_list[0][4].append((version, item, item_commit_list)) + + return note_version, re.sub(r"\.$", "", note_list[0][0]) + + ################################################################################################################################ + def _release_item_render(self): + """Add the details of each item that is not a development item, with the development items that name it.""" + + for item_list in self.release_item_map.values(): + for _, list_item, item, item_commit_list, dev_list in item_list: + self._detail_add(list_item, item, item_commit_list, dev_list=dev_list) + ################################################################################################################################ def render_document(self): """Build the release document.""" @@ -520,6 +683,8 @@ class _Release: self._release_render(release, release_section, version, commit_list, remaining_list, commit_map, check) + self._release_item_render() + return root ################################################################################################################################ @@ -536,15 +701,24 @@ class _Release: continue for item_type, item_title, item_name in _ITEM_LIST: - # Development items are only listed on a development build, since they are of no interest to a reader - if not self.dev and item_type == "release-development-list": - continue - item_node = xml_node_child(type_node, item_type) if item_node is None: continue + # Development items are only listed on a development build, since they are of no interest to a reader. Their + # commits are still claimed when detail is true. + if not self.dev and item_type == "release-development-list": + if detail and check: + for item in xml_node_child_list(item_node, "release-item"): + item_commit_list = self._item_commit( + item, xml_node_child_list(item, "p")[0], version, commit_list, remaining_list, commit_map, True + ) + + self._release_note_add(item, version, item_commit_list) + + continue + # A note about the release as a whole goes before the first list, whichever list that turns out to be if not note and xml_node_child(type_node, "text") is not None: xml_node_child_add( @@ -562,7 +736,11 @@ class _Release: for item in xml_node_child_list(item_node, "release-item"): text = xml_node_child_list(item, "p")[0] - item_check = check and item_type != "release-development-list" + + # Plain text of the item before credits are added + text_plain = self.render.process_text(text) if detail else None + + item_check = check and (detail or item_type != "release-development-list") item_commit_list = None if item_check or detail: @@ -570,7 +748,7 @@ class _Release: item, text, version, commit_list, remaining_list, commit_map, item_check ) - # An item written as more than one paragraph reads as one line in the release notes when version < 2.60 + # An item written as more than one paragraph reads as one line in the release notes when detail is false if not detail: for extra in xml_node_child_list(item, "p")[1:]: xml_node_content_add(text, " ") @@ -587,11 +765,70 @@ class _Release: xml_node_child_add(list_item, text) if detail: - self._detail_add(list_item, item, item_commit_list) + if item_type == "release-development-list": + release_note = self._release_note_add(item, version, item_commit_list) + self._detail_add(list_item, item, item_commit_list, release_note=release_note) + else: + if xml_node_child(item, "release-note") is not None: + raise ToolError( + "release %s item '%s' is not a development item and cannot name a release note" + % (version, text_plain) + ) + + # Details are added after every release is read + self.release_item_map.setdefault(version, []).append( + [text_plain, list_item, item, item_commit_list, []] + ) + + self._backpatch_render(release, release_section, version, commit_list, remaining_list, commit_map, check) + + # Every commit of the release is claimed by an item when detail and claim are true + if detail and check and self.claim and len(remaining_list) > 0: + self._commit_error("release %s has commits that no item claims" % version, remaining_list, commit_map) + + ################################################################################################################################ + def _backpatch_render(self, release, release_section, version, commit_list, remaining_list, commit_map, check): + """Render the commits of a release that were back-patched to a patch release, grouped by the version of the patch release. + + The commits are claimed on every build and only listed on a development build.""" + + backpatch_list = xml_node_child(release, "release-backpatch-list") + + if backpatch_list is None: + return + + list_node = None + + if self.dev: + heading = xml_node_add(release_section, "p") + xml_node_content_add(xml_node_add(xml_node_text_add(heading), "b"), "Back-Patched:") + list_node = xml_node_add(release_section, "list") + + for backpatch in xml_node_child_list(backpatch_list, "release-backpatch"): + backpatch_version = xml_node_attribute(backpatch, "version", True) + + if backpatch_version not in self.version_list or _VERSION_BUG_FIX_EXP.match(backpatch_version) is None: + raise ToolError("release %s back-patch version %s is not a patch release" % (version, backpatch_version)) + + if len(xml_node_child_list(backpatch, "commit")) == 0: + raise ToolError("release %s back-patch version %s has no commits" % (version, backpatch_version)) + + item_commit_list = self._item_commit(backpatch, None, version, commit_list, remaining_list, commit_map, check) + + if list_node is not None: + list_item = xml_node_text_add(xml_node_add(list_node, "list-item")) + + xml_node_content_add(list_item, "Back-patched to ") + xml_node_content_add(xml_node_add(list_item, "link", {"url": "#%s" % backpatch_version}), "v%s" % backpatch_version) + xml_node_content_add(list_item, ".") + + self._detail_add(list_item, backpatch, item_commit_list, True) #################################################################################################################################### -def release_render(root, path_doc, dev): - """Build the release document from the release list.""" +def release_render(root, path_doc, dev, claim=False): + """Build the release document from the release list. - return _Release(root, path_doc, dev).render_document() + When claim is true every commit of a release with version >= _DETAIL_VERSION_MIN must be claimed by an item.""" + + return _Release(root, path_doc, dev, claim).render_document() diff --git a/doc/resource/html/default.css b/doc/resource/html/default.css index 6a1ff2a88..edc4253b2 100644 --- a/doc/resource/html/default.css +++ b/doc/resource/html/default.css @@ -130,6 +130,9 @@ html font-family: var(--font-body); font-size: 16px; -webkit-text-size-adjust: 100%; + + /* Opening details does not scroll the page */ + overflow-anchor: none; } body diff --git a/doc/xml/release/2020s/2020/2.26.xml b/doc/xml/release/2020s/2020/2.26.xml index ff95d2cba..8e7526dae 100644 --- a/doc/xml/release/2020s/2020/2.26.xml +++ b/doc/xml/release/2020s/2020/2.26.xml @@ -15,10 +15,9 @@ - - +

Non-blocking TLS implementation.

diff --git a/doc/xml/release/2020s/2020/2.28.xml b/doc/xml/release/2020s/2020/2.28.xml index 8ebf26b01..ed29a4e99 100644 --- a/doc/xml/release/2020s/2020/2.28.xml +++ b/doc/xml/release/2020s/2020/2.28.xml @@ -19,8 +19,7 @@ - - +

Azure support for repository storage.

diff --git a/doc/xml/release/2020s/2020/2.29.xml b/doc/xml/release/2020s/2020/2.29.xml index 0d374065d..678c72fb5 100644 --- a/doc/xml/release/2020s/2020/2.29.xml +++ b/doc/xml/release/2020s/2020/2.29.xml @@ -33,10 +33,9 @@ - - +

Automatically retrieve temporary S3 credentials on AWS instances.

@@ -75,9 +74,8 @@ - - +

Improve memory usage of unlogged relation detection in manifest build.

diff --git a/doc/xml/release/2020s/2020/2.31.xml b/doc/xml/release/2020s/2020/2.31.xml index 065d77b21..3d050e673 100644 --- a/doc/xml/release/2020s/2020/2.31.xml +++ b/doc/xml/release/2020s/2020/2.31.xml @@ -46,8 +46,7 @@ - - +

Add repo-azure-endpoint option.

@@ -77,8 +76,7 @@ - - +

Improve performance of large file lists in backup/restore commands.

diff --git a/doc/xml/release/2020s/2021/2.32.xml b/doc/xml/release/2020s/2021/2.32.xml index d04b861e0..6aa2b378a 100644 --- a/doc/xml/release/2020s/2021/2.32.xml +++ b/doc/xml/release/2020s/2021/2.32.xml @@ -15,8 +15,7 @@ - - +

Add repo-ls command.

@@ -36,8 +35,7 @@ - - +

Add archive-mode-check option.

diff --git a/doc/xml/release/2020s/2021/2.33.xml b/doc/xml/release/2020s/2021/2.33.xml index dbe6cf33f..6f45f7af6 100644 --- a/doc/xml/release/2020s/2021/2.33.xml +++ b/doc/xml/release/2020s/2021/2.33.xml @@ -12,6 +12,8 @@

Fix option warnings breaking async archive-get/archive-push.

+ +

An option warning in the async process was logged to a closed stdout, which made the process abort. Since the async role can now have different valid options than the default role, this happened more often. Option warnings are now logged only for the default role.

@@ -25,6 +27,8 @@

Fix memory leak in backup during archive copy.

+ +

Copying WAL into the backup with archive-copy leaked memory, especially when the WAL needed to be recompressed.

@@ -38,6 +42,8 @@

Fix stack overflow in cipher passphrase generation.

+ +

The buffer for the generated passphrase had no room for the terminating zero. This was found on arm64 with musl libc.

@@ -51,6 +57,8 @@

Fix repo-ls / on S3 repositories.

+ +

S3 reports / as a file without the expected headers, which caused an error. / is now reported as not existing on storage that does not support paths.

@@ -99,20 +107,36 @@

Multiple repository support.

+ +

Up to four repositories may be configured, e.g. a local repository for fast restores and a remote repository for redundancy. archive-push pushes WAL to all repositories, and backups are scheduled for each repository. Some commands work with all repositories, while others require repo. repo is not required when only repo1 is configured.

- - - + + + + + + + + + + + + + + + + - - +

GCS support for repository storage.

+ +

Set repo-type=gcs to store the repository on GCS or a GCS-compatible object store.

@@ -126,6 +150,8 @@

Add archive-header-check option.

+ +

The WAL header is checked against the version and system identifier to make sure WAL is pushed to the correct stanza. The check is enabled by default and can be disabled when needed, e.g. for encrypted WAL.

@@ -140,6 +166,8 @@

Include recreated system databases during selective restore.

+ +

A system database (template0, template1, or postgres) that was recreated has an OID that makes it look like a user database. These databases are now always restored, whatever their OID.

@@ -153,22 +181,30 @@

Exclude content-length from S3 signed headers.

+ +

Some proxies modify the content-length header, which made authentication fail when it was signed.

+

Consolidate less commonly used repository storage options.

+ +

The S3 and Azure CA, host, port, and TLS verification options are renamed to repo-storage-*, e.g. repo1-s3-host is now repo1-storage-host. The old names are still accepted.

- - - + + + + + + @@ -176,6 +212,8 @@

Allow custom config-path default with ./configure --with-configdir.

+ +

Packagers can set a different default for config-path when building. Without the option the default is still /etc/pgbackrest.

@@ -197,6 +235,7 @@ + @@ -207,11 +246,86 @@ +

Add HttpUrl object.

+ + + + + + +

Move configuration definition to src/build/config/config.yaml.

+
+ + + + + + + + + + +

Improve storage drivers.

+
+ + + + + + + + + +

Improve the configure script.

+
+ + + + + + + + + + + +

Update help.auto.c missed in prior commits.

+
+ + + + + + + + + + + + + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Update config.guess and config.sub to latest versions.

+
@@ -226,6 +340,8 @@

Update reference to include links to user guide examples.

+ +

The command reference now links to the user guide sections with examples, and some descriptions were clarified, e.g. set for expire.

@@ -239,6 +355,8 @@

Update selective restore documentation with caveats.

+ +

Recovery may fail unless type=immediate is specified, because reports zeroed pages as errors after consistency is reached. On >= 13 ignore_invalid_pages may be used, but check the logs for invalid pages in the selected databases.

@@ -252,6 +370,8 @@

Add compress-type clarification to archive-copy documentation.

+ +

WAL must be recompressed when archive-push and backup use a different compress-type, which can be expensive.

@@ -264,6 +384,8 @@

Add compress-level defaults per compress-type value.

+ +

The defaults are 9 for bz2, 6 for gz, 1 for lz4, and 3 for zst.

@@ -278,5 +400,56 @@

Add note about required NFS settings being the same as .

+ + + + + + + + + + +

Fix option validity by role and make sections conform to C help.

+
+ + + + + + + + + + + +

Improve the documentation build and release notes.

+
+
+ + + + + + + + + + + + + + + + + + + + + +

Improve unit tests and test tools.

+
+
+
diff --git a/doc/xml/release/2020s/2021/2.34.xml b/doc/xml/release/2020s/2021/2.34.xml index 6ee5cd6e3..09494c804 100644 --- a/doc/xml/release/2020s/2021/2.34.xml +++ b/doc/xml/release/2020s/2021/2.34.xml @@ -10,11 +10,12 @@ - - +

Fix issues with leftover spool files from a prior restore.

+ +

A notification left in the spool path by a prior restore could make archive-get report a WAL segment as missing. When this notification is found on the first check, it is now removed and the async process is run again. An error is reported when the async process does not respond, rather than reporting the WAL segment as missing.

@@ -25,11 +26,12 @@ - - +

Fix issue when checking links for large numbers of tablespaces.

+ +

The link check used a lot of memory with many tablespaces and could crash. The new check is much faster, uses far less memory, and also detects duplicate file links.

@@ -43,6 +45,8 @@

Free no longer needed remotes so they do not timeout during restore.

+ +

The connections to remotes were held for the whole restore and could time out, which logged a harmless but distracting warning at the end of a long restore. They are now closed after the manifest is loaded.

@@ -50,10 +54,13 @@ +

Fix help when a valid option is invalid for the specified command.

+ +

help segfaulted when asked about an option that is not valid for the command.

@@ -67,6 +74,8 @@

Add PostgreSQL 14 support.

+ +

14 needs no code changes from 13. The catalog version may now change during the beta/rc period without requiring a new release.

@@ -79,11 +88,12 @@ - - +

Add automatic GCS authentication for GCE instances.

+ +

Set repo-gcs-key-type=auto to get the authentication token from the instance metadata on a GCE instance.

@@ -96,6 +106,8 @@

Add repo-retention-history option to expire backup history.

+ +

Set the number of days of backup history to keep. By default all history is kept, and history for backups still in the repository is never expired. When a full backup manifest expires, the manifests of its differential and incremental backups expire as well.

@@ -108,6 +120,8 @@

Add db-exclude option.

+ +

Restore excludes the specified databases by writing them as sparse, zeroed files. can still perform recovery, and the databases can be dropped after recovery. With db-include, db-exclude applies only to the system databases template0, template1, and postgres.

@@ -134,10 +148,12 @@

Remove stanza archive spool path on restore.

+ +

Files in the spool path could interfere with the new cluster, e.g. old archive-push acknowledgements could make it skip archiving WAL.

- + @@ -147,6 +163,8 @@

Do not write files atomically or sync paths during backup copy.

+ +

Atomic writes are not needed since checksums are validated when a failed backup is resumed, and all paths are synced at the end of the backup.

@@ -206,6 +224,7 @@ + @@ -222,8 +241,13 @@ + + + + +

Add local process shim.

@@ -231,6 +255,7 @@ + @@ -238,6 +263,8 @@ + + @@ -265,6 +292,70 @@

Simplify defaults for --force option.

+ + + + + + + + + + + + + + + + + + + + + + + + + +

Refactor modules with inline getters/setters.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Update config.sub to latest version.

+
@@ -280,6 +371,8 @@

Update contributing documentation.

+ +

The contributing guide has more examples of how to write code, add configuration options, and test.

@@ -291,6 +384,8 @@

Consolidate RHEL/CentOS user guide into a single document.

+ +

The second guide existed mainly to document stop-auto for <= 9.5, which is now EOL. The option is still documented in the reference.

@@ -304,5 +399,81 @@

Clarify that repo-s3-role is not an ARN.

+ + + + + + + + + + +

Update the user guide and release documentation.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +

Improve test harness macros.

+
+ + + + + + + + + + + + + + + + + + +

Improve unit tests and test tools.

+
+ + + + + + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2021/2.35.xml b/doc/xml/release/2020s/2021/2.35.xml index 042732eec..c5e1f6cfa 100644 --- a/doc/xml/release/2020s/2021/2.35.xml +++ b/doc/xml/release/2020s/2021/2.35.xml @@ -21,11 +21,12 @@ - - +

Detect errors in S3 multi-part upload finalize.

+ +

Completing a multi-part upload can fail even when S3 returns HTTP success. A response without an ETag is now treated as a failure, and the job is retried.

@@ -39,10 +40,12 @@

Fix detection of circular symlinks.

+ +

Links were followed before they were checked, and a circular link sent the manifest build into endless recursion and a crash.

- + @@ -53,6 +56,8 @@

Only pass selected repo options to the remote.

+ +

Options for other repositories could cause conflicts on the remote, which uses exactly one repository.

@@ -71,6 +76,8 @@

Binary protocol.

+ +

Local and remote processes now communicate with the binary pack format rather than JSON. Packs are more compact, faster to render and parse, and strictly typed. Each message is written in one place, which makes an error less likely to leave the protocol in a bad state, and messages have no size limit.

@@ -84,11 +91,13 @@

Automatically create data directory on restore.

+ +

A check migrated from Perl prevented restore from creating the data directory.

- - + + @@ -97,6 +106,8 @@

Allow restore --type=lsn.

+ +

Set type=lsn and an LSN in target to recover to an LSN on >= 10.

@@ -110,11 +121,13 @@

Change level of backup/restore copied file logging to detail.

+ +

This makes the info log level less noisy. Set the log level to detail to see each copied file.

- - + + @@ -123,6 +136,8 @@

Loop while waiting for checkpoint LSN to reach replay LSN.

+ +

On a standby the checkpoint LSN can lag slightly behind the replay LSN until pg_control is updated. The backup now keeps checking rather than failing.

@@ -134,12 +149,18 @@

Log backup file total and restore size/file total.

+ +

The backup size is now logged at the end of the backup and includes files added to the manifest after the main copy, e.g. backup_label and WAL. Restore now logs its size and file total.

- + + + + + @@ -159,6 +180,102 @@

Clear error when a CATCH() block finishes.

+ + + + + + + + + + + + + + + + + + + + + + + +

Migrate config and error code generation to C.

+
+ + + + + + +

Fix miscalculation in time option command defaults.

+
+ + + + + + + + + + +

Refactor local/remote startup.

+
+ + + + + + +

Fix infinite loop in protocolServerProcess() on error.

+
+ + + + + + +

Add temp mem context reset blocks in job processing loops.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Update config.guess and config.sub to latest versions.

+
@@ -174,6 +291,8 @@

Fix incorrect host names in user guide.

+ +

Some examples showed pg1 rather than the host name, and the install block installed packages on the build host no matter which host was specified.

@@ -192,6 +311,8 @@

Update contributing documentation and add pull request template.

+ +

The contributing guide now has a table of contents and sections on understanding test output and submitting a pull request. GitHub now shows a template for new pull requests.

@@ -203,6 +324,8 @@

Rearrange backup documentation in user guide.

+ +

The Fast Start Option and Archive Timeout sections moved to Quick Start - Perform Backup. The Automatic Stop Option section, which applies only to <= 9.6, was removed.

@@ -212,6 +335,8 @@

Clarify restore --type behavior in command reference.

+ +

The reference now states that set must be specified when the target is before the latest backup and type is not time.

@@ -225,6 +350,29 @@

Fix documentation and comment typos.

+ + + + + + + + + + + + +

Add optional stress test section to the user guide.

+
+ + + + + + +

Add linefeeds around content even when not in pretty mode.

+
+
@@ -240,6 +388,8 @@

Add check for test path inside repo path.

+ +

A test path inside the repository path caused strange failures because the repository is copied into the test path. test.pl now errors in this case.

@@ -251,6 +401,8 @@

Add CodeQL static code analysis.

+ +

CodeQL now runs in CI. Issues it found were fixed, e.g. gmtime()/localtime() were replaced with gmtime_r()/localtime_r().

@@ -328,5 +480,73 @@

Update tests to use standard patterns.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Improve test harness macros.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +

Improve unit tests and test tools.

+
+ + + + + + + + + + +

CI updates.

+
+
diff --git a/doc/xml/release/2020s/2021/2.36.xml b/doc/xml/release/2020s/2021/2.36.xml index f528b2da0..79ddde298 100644 --- a/doc/xml/release/2020s/2021/2.36.xml +++ b/doc/xml/release/2020s/2021/2.36.xml @@ -12,6 +12,8 @@

Allow global as a stanza prefix.

+ +

A stanza name that begins with global, e.g. global_stanza, was rejected because the config parser treated it as a global section.

@@ -24,6 +26,8 @@

Fix segfault on invalid GCS key file.

+ +

A GCS key file without the client email, private key, or token URI caused a segfault. It now causes an error.

@@ -45,6 +49,8 @@

Allow link-map option to create new links.

+ +

link-map could only remap links that were in the backup. It can now create a new link for any path or file in the backup.

@@ -59,9 +65,12 @@

Increase max index allowed for pg/repo options to 256.

+ +

The maximum index was 8 for pg options and 4 for repo options. Both are now 256, e.g. pg256-path.

+ @@ -72,12 +81,23 @@ - - +

Add WebIdentity authentication for AWS S3.

+ +

Set repo-s3-key-type=web-id to get credentials automatically in an EKS environment.

+
+ + + + + + +

Add repo-azure-uri-style option.

+ +

Set repo-azure-uri-style to host (default) or path to select the URI style for Azure. Azurite uses host-style URIs when the endpoint looks like a multipart host name.

@@ -90,6 +110,8 @@

Report backup file validation errors in backup.info.

+ +

Errors found during a backup, e.g. invalid page checksums, were shown only by info with set. A flag in backup.info now shows in text and JSON output that a backup has errors. The details still require set.

@@ -104,6 +126,8 @@

Add recovery start time to online backup restore log.

+ +

Restore now logs the time that recovery will start from, which shows how much WAL must be replayed.

@@ -119,6 +143,8 @@

Report original error and retries on local job failure.

+ +

When a local job fails after its retries, the error now reports the first error with its stack trace, followed by the retry errors. Before, only the last error was reported, which was often a cascade failure such as the protocol being out of sync.

@@ -130,6 +156,8 @@

Rename page checksum error to error list in info text output.

+ +

The label in info text output is now error list rather than page checksum error. A file may have an alignment error rather than a page checksum error.

@@ -143,12 +171,15 @@

Add hints to standby replay timeout message.

+ +

The timeout waiting for the standby to replay now has hints to check that replication is running and to disable backup-standby to back up from the primary.

- + + @@ -156,8 +187,7 @@ - - +

Add TLS server.

@@ -173,10 +203,186 @@

Store config values as a union instead of a variant.

+ + + + + + + + + + + + +

Migrate command-line help generation to C.

+
+ + + + + + + + + + + + + + + + +

Improve the Pack type and use it for filters and configuration rules.

+
+ + + + + + + + + + + + +

Simplify configuration rules.

+
+ + + + + + + + + + + + + + + +

Improve memory allocation and mem context handling.

+
+ + + + + + +

Add configurable storage helpers to create repository storage.

+
+ + + + + + +

More efficient generation of diff/incr backup label.

+
+ + + + + + + + + +

Add -Werror -Wfatal-errors -g flags to configure --enable-test.

+
+ + + + + + + + +

Add required header for Illumos.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Finalize catalog number for PostgreSQL 14 release.

+
+ + + + + + +

Update config.guess and config.sub to latest versions.

+
+ + + + + + + + +

Fix incorrect host name in user guide.

+ +

The replication setup used the IP address of pg-primary in pg_hba.conf rather than the IP address of pg-standby.

+
+
+ + + + + + + + + + + +

Improve option documentation.

+ +

The help for buffer-size now describes all the operations that use it, the descriptions of cmd-ssh, repo-host-cmd, and pg-host-cmd are consistent, and archive-header-check moved to the archive section of the configuration reference.

+
+
+ @@ -193,6 +399,88 @@

Eliminate linefeed formatting from documentation.

+ + + + + + + + + + + + + + +

Update the user guide and documentation build.

+
+ + + + + + + + + +

Add analytics to the HTML documentation.

+
+ + + + + + + + + + + + +

Update the index page, README.md, and contributing documentation.

+
+ + + + + + + + + + + + + + + + + + + + + + + +

Improve unit tests and test tools.

+
+ + + + + + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2022/2.37.xml b/doc/xml/release/2020s/2022/2.37.xml index 35e782007..1f3f01b37 100644 --- a/doc/xml/release/2020s/2022/2.37.xml +++ b/doc/xml/release/2020s/2022/2.37.xml @@ -16,6 +16,8 @@

Fix restore delta link mapping when path/file already exists.

+ +

When link-map or link-all mapped a path or file that already existed to a link, a delta restore left the existing path or file in place. It is now replaced by the link.

@@ -29,6 +31,8 @@

Fix socket leak on connection retries.

+ +

In optimized builds the socket of a failed connection attempt was not closed, and each retry leaked a socket.

@@ -46,11 +50,12 @@ - - +

Add TLS server.

+ +

The server command starts a TLS server that can be used instead of SSH to reach repository and hosts. Set repo-host-type=tls or pg-host-type=tls on the client, and configure certificates and client authorization with the tls-server-* options. SIGHUP reloads the configuration and SIGTERM stops the server.

@@ -65,6 +70,8 @@

Add --cmd option.

+ +

Set cmd to the executable used in commands that writes, e.g. restore_command in recovery.conf.

@@ -80,6 +87,8 @@

Check archive immediately after backup start.

+ +

A backup failed because WAL archiving was not working only after all files were copied. The archive is now checked right after the backup starts. On an idle system a restore point is created to switch the WAL segment.

@@ -92,6 +101,8 @@

Add timeline and checkpoint checks to backup.

+ +

The backup now checks that pg_control has the checkpoint and timeline of the backup start, and that a standby is following the primary, i.e. it is on the same timeline and its checkpoint is not later than the backup checkpoint.

@@ -103,6 +114,8 @@

Check that clusters are alive and correctly configured during a backup.

+ +

A backup now fails as soon as a cluster stops or the standby is promoted. Before, a stopped primary was detected only at the end of the backup and a promoted standby was not detected.

@@ -117,6 +130,8 @@

Error when restore is unable to find a backup to match the time target.

+ +

This was a warning that was easy to miss, and a lot of time could be lost restoring a backup that cannot reach the target.

@@ -129,6 +144,8 @@

Parse protocol/port in S3/Azure endpoints.

+ +

repo-s3-endpoint, repo-azure-endpoint, and repo-storage-host may now include a protocol and port, e.g. https://host:9000.

@@ -140,6 +157,8 @@

Add warning when checkpoint_timeout exceeds db-timeout.

+ +

With start-fast=n, a backup can time out waiting for the checkpoint when checkpoint_timeout is greater than db-timeout. The backup now warns in this case.

@@ -185,6 +204,8 @@

Make backup size logging exactly match info command output.

+ +

The logged backup size now includes only the files copied, plus backup_label and tablespace_map. Before, e.g. an incremental backup after a switchover logged the size of every file checked.

@@ -218,6 +239,53 @@

Add StringId as an option type.

+ + + + + + +

Do not delete manifests individually during stanza delete.

+
+ + + + + + + + + + +

Add error type and message to CHECK() macro.

+
+ + + + + + + + + + + + + + + + + +

Clean up and refactor code.

+
+ + + + + + +

Update LICENSE.txt and PostgreSQL copyright for 2022.

+
@@ -254,7 +322,52 @@

Remove obsolete statement about future multi-repository support.

+ +

The documentation stated that only one repository was allowed, but multiple repositories have been supported since v2.33.

+ + + + + + + + + + +

Update the user guide.

+
+ + + + + + + + + +

Update the release notes and RELEASE.md.

+
+
+ + + + + + + + + + + + + + + +

Improve unit and performance tests.

+
+
+
diff --git a/doc/xml/release/2020s/2022/2.38.xml b/doc/xml/release/2020s/2022/2.38.xml index 39085407d..712620c70 100644 --- a/doc/xml/release/2020s/2022/2.38.xml +++ b/doc/xml/release/2020s/2022/2.38.xml @@ -16,6 +16,8 @@

Retry errors in S3 batch file delete.

+ +

A failed batch delete was retried, but errors for individual files in the batch were not, and could terminate during expire or when removing a backup that could not be resumed. Files that fail in a batch are now deleted individually with the usual HTTP retries.

@@ -29,6 +31,8 @@

Allow case-insensitive matching of HTTP connection header values.

+ +

The HTTP specification allows connection header values in any case, e.g. Close.

@@ -40,11 +44,12 @@ - - +

Add support for AWS S3 server-side encryption using KMS.

+ +

Set repo-s3-kms-key-id to encrypt objects with a key managed by AWS KMS.

@@ -56,6 +61,8 @@

Add archive-missing-retry option.

+ +

By default archive-get retries a WAL segment it already reported as missing, which ignores missing notifications left in the spool path by a prior restore. With archive-missing-retry=n, can detect the end of the archive and switch to streaming even while WAL is being archived. The spool path must then be empty when recovery starts.

@@ -68,6 +75,8 @@

Add backup type filter to info command.

+ +

Set type to show only backups of that type, e.g. type=full.

@@ -90,6 +99,8 @@

Retry on page validation failure during backup.

+ +

A page that fails checksum validation is now read again. It is reported as an error only when it has not changed. A changed page is being written by , and the WAL contains a full page image. Zero pages are now checked to be all zeroes rather than only by the pd_upper field.

@@ -98,13 +109,14 @@ - - +

Handle TLS servers that do not close connections gracefully.

+ +

Some servers close the socket rather than the TLS connection. When a response has no content length or chunked encoding and its content can be parsed, the closed socket is now treated as EOF. These servers stopped working in v2.35.

@@ -116,6 +128,8 @@

Add backup LSNs to info command output.

+ +

The start and stop LSNs of a backup are shown with set and in JSON output, for use with LSN-based Point-in-Time Recovery.

@@ -127,12 +141,16 @@

Automatically strip trailing slashes for repo-ls paths.

+ +

A trailing slash on the path made repo-ls show no content on some repository storage types.

- + + + @@ -140,6 +158,8 @@

Do not retry fatal errors.

+ +

Retrying fatal errors, especially out of memory errors, may cause lockups. Assertion and memory errors are now reported without retrying.

@@ -152,6 +172,8 @@

Remove support for PostgreSQL 8.3/8.4.

+ +

There is no evidence that these versions are still in use and supporting them costs development and test time. Use an older version of to back up or migrate from these versions.

@@ -164,6 +186,8 @@

Remove logic that tried to determine additional file system compression.

+ +

After a file was copied, checked its size on disk to detect compression by the file system, e.g. ZFS. This was untested, slow with many small files, and blocked file bundling. The repository size in info is now what wrote.

@@ -172,7 +196,6 @@ - @@ -183,18 +206,29 @@ - + + + + - + + + - + + + - + + + - + + + @@ -216,14 +250,17 @@ + - + + + -

Add percent complete to lock file.

+

Refactor lock code.

@@ -242,6 +279,53 @@

Configuration refactoring.

+ + + + + + +

Add XML to invalid XML error message.

+
+ + + + + + +

Fix invalid file descriptor being passed to close().

+
+ + + + + + +

Add ioCopy().

+
+ + + + + + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Update config.guess and config.sub to latest versions.

+
@@ -254,6 +338,8 @@

Move repo options in TLS documentation to the global section.

+ +

The user guide set these options in the stanza section, which works in some cases but is not best practice.

@@ -263,6 +349,8 @@

Remove unused backup-standby option from stanza commands.

+ +

stanza-create and stanza-upgrade listed backup-standby in the command reference and help, but did not use it.

@@ -288,6 +376,8 @@

Add aliveness check to systemd service configuration.

+ +

The pgbackrest.service example now checks that the server is still running shortly after it starts. Before, a server that failed to start reported no error while systemd retried in the background.

@@ -301,6 +391,8 @@

Add FAQ explaining WAL archive suffix.

+ +

The suffix on a WAL file in the repository is its SHA1 checksum, which is used to verify the file. It cannot be omitted.

@@ -317,5 +409,67 @@

Note that replications slots are not restored.

+ + + + + + + + + + + + +

Update the user guide.

+
+ + + + + + + + + +

Improve the documentation build.

+
+ + + + + + + + + +

Update the release notes and NEWS.md.

+
+
+ + + + + + + + + + +

Improve unit tests.

+
+ + + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2022/2.39.xml b/doc/xml/release/2020s/2022/2.39.xml index 6ddea8859..9a7d962a6 100644 --- a/doc/xml/release/2020s/2022/2.39.xml +++ b/doc/xml/release/2020s/2022/2.39.xml @@ -5,7 +5,6 @@ - @@ -16,6 +15,8 @@

Fix error thrown from FINALLY() causing an infinite loop.

+ +

An error thrown in a FINALLY() block returned to the same block, where the error was likely thrown again and caused an infinite loop. FINALLY() now runs only once.

@@ -26,11 +27,12 @@ - - +

Error on all lock failures except another process holding the lock.

+ +

archive-get/archive-push did not error when the lock could not be taken for another reason, e.g. permissions, and the async process was not launched. The user got a generic failure message and there was no async log. These failures are now errors.

@@ -60,6 +62,8 @@

Backup file bundling for improved small file support.

+ +

Bundling stores small files together in the repository to save time and space during backup, especially on object stores where creating each file is expensive. Enable it with repo-bundle and tune it with repo-bundle-size and repo-bundle-limit. Restore reads adjacent files in a bundle with a single read.

@@ -75,6 +79,8 @@

Verify command to validate the contents of a repository.

+ +

The verify command checks that the backups and WAL in the repository are valid. Set output=text to print the results and verbose to include what was verified successfully along with errors.

@@ -91,10 +97,12 @@

15 support.

+ +

15 removes exclusive backup, renames the backup start/stop functions, and drops pg_database.datlastsysoid, which no longer uses.

- + @@ -106,6 +114,8 @@

Show backup percent complete in info output.

+ +

info shows the percent complete of a running backup on the host where the backup is running. JSON output reports it as an integer, the percent times 100.

@@ -122,6 +132,8 @@

Auto-select backup for restore command --type=lsn.

+ +

With type=lsn, restore now selects the most recent backup that stopped at or before the target LSN.

@@ -133,6 +145,8 @@

Suppress existing WAL warning when archive-mode-check is disabled.

+ +

With archive-mode-check=n and WAL pushed from multiple hosts, a WAL file already in the archive with the same checksum is expected and no longer logs a warning. A different checksum is still an error.

@@ -145,6 +159,8 @@

Add AWS IMDSv2 support.

+ +

IMDSv2 protects the instance metadata that provides credentials for repo-s3-key-type=auto. falls back to IMDSv1 when the IMDSv2 token request fails.

@@ -158,6 +174,8 @@

Allow repo-hardlink option to be changed after full backup.

+ +

Changing repo-hardlink required a new full backup. It can now be changed at any time, e.g. to disable it for file bundling.

@@ -169,6 +187,8 @@

Increase precision of percent complete logging for backup and restore.

+ +

Percent complete is now logged with hundredths, which gives more frequent updates for large backups and restores.

@@ -185,6 +205,8 @@

Improve path validation for repo-* commands.

+ +

A path may not contain //, a trailing / is removed, and an absolute path must be in the repository path.

@@ -198,6 +220,8 @@

Improve stop command to honor stanza option.

+ +

stop with force and stanza now terminates only the processes holding locks for that stanza. Before, it terminated processes for all stanzas.

@@ -211,6 +235,8 @@

Improve error message for invalid repo-azure-key.

+ +

With repo-azure-key-type=shared, repo-azure-key is now checked for valid base64.

@@ -222,6 +248,8 @@

Add hint to check the log on archive-get/archive-push async error.

+ +

When the async process cannot write its status files, archive-get/archive-push times out with a generic error. The error now includes a hint with the path of the async log, which contains the actual error.

@@ -246,6 +274,8 @@

Strip extensions from history manifest before showing in error message.

+ +

When a new backup label was not later than the latest label from the backup history, the error showed the history manifest name, e.g. 20220504-222042F_20220504-222141I.manifest.gz. It now shows only the label.

@@ -258,6 +288,16 @@

Add user:group to lock permission error.

+ + + + + + +

Add hint when unable to find the primary cluster.

+ +

The unable to find primary cluster error now includes a hint asking whether all available clusters are in recovery.

+
@@ -298,7 +338,7 @@ - + @@ -336,6 +376,161 @@

Refactor PgClient to return results in Pack format.

+ + + + + + + + + + + + + + +

Fix undefined behavior found by sanitizers.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Fix memory leaks and improve memory context usage.

+
+ + + + + + + + + + + + + + + + + + +

Add and improve macros.

+
+ + + + + + + + + + + + + + + + + + + +

Add and improve string functions.

+
+ + + + + + +

Refactor remote storage protocol to use Packs instead of JSON.

+
+ + + + + + +

Fix reported error line number when ini key length is zero.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Update config.guess and config.sub to latest versions.

+
@@ -357,6 +552,8 @@

Fix example for repo-gcs-key-type option in configuration reference.

+ +

The example was none, which is not a valid value. It is now auto.

@@ -366,6 +563,8 @@

Fix tls-server-auth example and add clarifications.

+ +

The example was missing the client CN and is now client-cn=stanza1. The help also states that wildcards are not allowed for the client CN.

@@ -381,6 +580,8 @@

Simplify messaging around supported versions in the documentation.

+ +

The user guides listed version ranges, which made it look like other versions were not supported, e.g. 12 on RHEL. The ranges were removed and the introduction now explains which versions the user guides cover.

@@ -392,6 +593,8 @@

Add option type descriptions.

+ +

The configuration reference now describes each option type, e.g. the units for size options, rather than repeating the description for each option.

@@ -403,10 +606,12 @@

Add FAQ about backup types and restore speed.

+ +

A new FAQ explains that the backup type affects only the backup and not how fast a restore runs.

- + @@ -414,8 +619,30 @@

Document required base branch for pull requests.

+ +

The contributing guide now states that pull requests must be based on the integration branch.

+ + + + + + + + + + + + + + + + + +

Fix typos and formatting in the documentation and help.

+
+
@@ -430,6 +657,51 @@

Remove integration expect log testing.

+ + + + + + + + + + + + + + + + + + + + + + + + + +

Improve unit tests and test tools.

+
+ + + + + + + + + + + + + + + + +

CI updates.

+
diff --git a/doc/xml/release/2020s/2022/2.40.xml b/doc/xml/release/2020s/2022/2.40.xml index 03bb3fd50..39c30b534 100644 --- a/doc/xml/release/2020s/2022/2.40.xml +++ b/doc/xml/release/2020s/2022/2.40.xml @@ -14,11 +14,18 @@

OpenSSL 3 support.

+ +

now builds with OpenSSL 3. Deprecation warnings are suppressed, and an unexpected EOF is detected with the error codes that OpenSSL 3 reports.

- - + + + + + + + @@ -27,6 +34,8 @@

Create snapshot when listing contents of a path.

+ +

A path listed without sorting was read while its entries were processed. When files were deleted during the listing, some filesystems skipped files that still existed and the path could not be removed. Listings now always use a snapshot of the path.

@@ -38,6 +47,8 @@

Force target-timeline=current when restore type=immediate.

+ +

On >= 12 the default target timeline is latest, and recovery could fail when the latest timeline in the repository cannot be reached from the backup. Restore with type=immediate does not change timelines, so it now sets the target timeline to current.

@@ -49,6 +60,8 @@

Truncate files during delta restore when they are larger than expected.

+ +

Delta restore copied a file from the repository whenever its size differed from the manifest. A larger file is now truncated to the size in the manifest and copied only when its checksum does not match. Files that were only appended to, e.g. logs, are no longer copied.

@@ -60,6 +73,8 @@

Disable incremental manifest save when resume=n.

+ +

During a backup the manifest is saved periodically for use by resume. These saves are now skipped when resume=n.

@@ -71,6 +86,8 @@

Set backup percent complete to zero before copy start.

+ +

The progress of a running backup was not reported until the first file was copied. It is now set to zero when copying starts.

@@ -81,11 +98,12 @@ - - +

Use S3 IsTruncated flag to determine list continuation.

+ +

Recent versions of Scality send an empty NextContinuationToken when a list is not truncated, which caused an infinite loop. The IsTruncated flag now determines whether a list continues, and a missing or empty token for a truncated list is an error.

@@ -144,6 +162,77 @@

Fix hard-coded WAL size assertion in walSegmentNext().

+ + + + + + + + + +

Add labels in parse.auto.c to make diffs easier to read.

+
+ + + + + + + + + +

Fix repository option definitions for the backup and stanza commands.

+
+ + + + + + +

Use storagePathP() instead of cfgOptionStr() to get base repo path.

+
+ + + + + + +

Add additional detail to warnings when delta checksum is auto-enabled.

+
+ + + + + + + + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Replace AC_PROG_CC_C99 configure macro with AC_PROG_CC.

+
+ + + + + + +

Update config.guess to latest version.

+
@@ -156,11 +245,15 @@

Skip internal options in the configuration reference.

+ +

Options that are internal only for some commands were listed in the configuration reference. The command-line help was not affected.

+ + @@ -170,12 +263,40 @@

Add link to configuration in repository host section.

+ + + + + + + +

Fix RHEL container build for documentation.

+
+ + + + + + + + + +

Update release notes.

+
+
- + + + + + + + + @@ -184,6 +305,8 @@

Add experimental Meson build.

+ +

Meson has simpler syntax and better performance than autoconf/make. It is used for code generation and test builds, and errors on anything but a debug build. Packagers should continue to use autoconf/make.

@@ -206,7 +329,53 @@

Fix compile error when DEBUG_EXEC_TIME is defined without DEBUG.

+ +

Without DEBUG the ASSERT() that used the start time expanded to nothing, and the unused variable caused a compile error. The check now uses CHECK().

+ + + + + + + + + + + + + + + + +

Add experimental unit test harness written in C.

+
+ + + + + + + + + +

Improve unit and integration tests.

+
+ + + + + + + + + + + + +

CI updates.

+
+
diff --git a/doc/xml/release/2020s/2022/2.41.xml b/doc/xml/release/2020s/2022/2.41.xml index c4fd2b0a4..578662ec9 100644 --- a/doc/xml/release/2020s/2022/2.41.xml +++ b/doc/xml/release/2020s/2022/2.41.xml @@ -12,6 +12,8 @@

Fix incorrect time expiration being used for non-default repositories.

+ +

When expire ran without repo, the time-based repo-retention-full for every repository was read from the lowest-numbered repository. Each repository now uses its own value.

@@ -25,6 +27,8 @@

Fix issue when listing directories recursively with a filter.

+ +

repo-ls with recurse and filter could fail with a double free or segfault when the last entry in a directory was a directory that had entries. A parent list was freed before the entries of its subdirectories were processed.

@@ -40,6 +44,8 @@

Backup key/value annotations.

+ +

Add key/value annotations to a backup with the annotation option of the backup command, and add, modify, or remove them later with the new annotate command. The info command shows annotations in text output when set is specified and always includes them in JSON output.

@@ -55,11 +61,16 @@

Support --set in JSON output for info command.

+ +

With set, JSON output from info now includes the details that text output already showed, e.g. the error and tablespace lists.

- - + + + + + @@ -68,6 +79,8 @@

Allow upload chunk size to be configured for object stores.

+ +

Set repo-storage-upload-chunk-size to change the size of each upload chunk for S3, GCS, or Azure. Larger chunks can improve performance but use more memory. The defaults are unchanged.

@@ -81,6 +94,8 @@

Update archive.info timestamps after a successful backup.

+ +

archive.info and its copy were written only by stanza-create and stanza-upgrade, and an object store lifecycle policy that expires old files could remove them. Their timestamps are now updated after each successful backup.

@@ -91,11 +106,12 @@ - - +

Move standby timeline check after checkpoint.

+ +

The check that the standby is on the expected timeline used pg_control as it was before the backup started. Right after a promotion the standby may not have written the new timeline to pg_control yet, and the backup failed with standby is on timeline ... but expected .... The check now runs after the checkpoint.

@@ -105,6 +121,8 @@

Improve warning message on backup resume.

+ +

The warning read as if the user needed to take action. It now states that invalid files will be removed and then the backup will resume.

@@ -145,6 +163,33 @@

Add FN_INLINE_ALWAYS macro.

+ + + + + + +

Clear ProtocolClient callback after connection error.

+
+ + + + + + + + + +

Improve the code builder.

+
+ + + + + + +

Update config.guess to latest version.

+
@@ -157,7 +202,82 @@

Add absolute path for kill in pgbackrest.service.

+ +

The pgbackrest.service example now uses /bin/kill in ExecReload. Older versions of systemd require an absolute path.

+ + + + + + + +

Allow host memory limits in the user guide to be disabled.

+
+ + + + + + + + +

Add missed reviewer to the release notes.

+
+
+ + + + + + + + + + + + + + + + +

Build unit and performance tests with the C test harness.

+
+ + + + + + + + + + + + + +

Improve unit tests and test tools.

+
+ + + + + + +

Update Minio test/documentation container version.

+
+ + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2022/2.42.xml b/doc/xml/release/2020s/2022/2.42.xml index 892874fa3..a56d97be9 100644 --- a/doc/xml/release/2020s/2022/2.42.xml +++ b/doc/xml/release/2020s/2022/2.42.xml @@ -9,15 +9,19 @@ - - +

Fix memory leak in file bundle backup/restore.

+ +

Restore freed some I/O objects for bundled files only after every file in the bundle was restored. With many small files in a bundle, memory use grew until restore failed with unable to allocate. Backup had a similar, smaller leak when resuming.

- + + + + @@ -25,6 +29,8 @@

Fix protocol error on short read of remote file.

+ +

A remote file read that stopped early or failed partway left the protocol in a bad state. The next command failed with client state is 'data-get' but expected 'idle' and the original error was lost. The rest of the file is now read when the file is closed.

@@ -38,6 +44,8 @@

Do not store references for zero-length files when bundling.

+ +

Bundled diff/incr backups stored a reference to a prior backup for zero-length files, which are not stored in any backup. The reference was ignored on restore but used space in the manifest.

@@ -51,11 +59,14 @@

Use more generic descriptions for pg_start_backup()/pg_stop_backup().

+ +

15 renamed these functions to pg_backup_start()/pg_backup_stop(). The logs and documentation now use descriptions that do not depend on the version.

+ @@ -65,6 +76,7 @@ + @@ -88,10 +100,11 @@ -

Block incremental backup.

+

Block incremental backup groundwork.

+ @@ -102,9 +115,69 @@

Move link creation to storage interface.

+ + + + + + + + + +

Do not log bundle info when a file is delta matched from a prior backup.

+
+ + + + + + +

Return binary as result from CryptoHash filter.

+
+ + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Finalize catalog number for PostgreSQL 15 release.

+
+ + + + + + +

Update config.guess and config.sub to latest versions.

+
+ + + + + + + + + +

Add missed release note for v2.41.

+
+
+
+ @@ -116,7 +189,34 @@

Update test.pl --psql-bin option to match command-line help.

+ +

The help showed --psql-bin but the option was named --pgsql-bin. The option now has the name shown in the help.

+ + + + + + + + + + +

Improve unit tests and test tools.

+
+ + + + + + + + + + +

CI updates.

+
+
diff --git a/doc/xml/release/2020s/2022/2.43.xml b/doc/xml/release/2020s/2022/2.43.xml index be506bd34..0231a1a47 100644 --- a/doc/xml/release/2020s/2022/2.43.xml +++ b/doc/xml/release/2020s/2022/2.43.xml @@ -2,8 +2,11 @@ - - + + + + + @@ -14,6 +17,8 @@

Fix missing reference in diff/incr backup.

+ +

In v2.42 a diff or incr backup failed with unable to find '...' in string list when its prior backup was made by an earlier version. The reference list built for a manifest from an earlier version now includes the backup's own label.

@@ -28,7 +33,19 @@

Add hint when an option is specified without an index.

+ +

An option that requires an index, e.g. repo-storage-ca-file, now errors with a hint that shows the indexed name, e.g. repo1-storage-ca-file. A deprecated option also gets a hint with its current name.

+ + + + + + + +

Update config.guess and config.sub to latest versions.

+
+
diff --git a/doc/xml/release/2020s/2023/2.44.xml b/doc/xml/release/2020s/2023/2.44.xml index 28d226c60..9e3ebf811 100644 --- a/doc/xml/release/2020s/2023/2.44.xml +++ b/doc/xml/release/2020s/2023/2.44.xml @@ -10,6 +10,8 @@

Remove support for PostgreSQL 9.0/9.1/9.2.

+ +

now supports ten versions of : the five supported versions and the last five EOL versions. As of 15 that excludes 9.0, 9.1, and 9.2.

@@ -23,6 +25,8 @@

Restore errors when no backup matches the current version of .

+ +

After a stanza-upgrade with no new backup, restore used the latest backup, which was made from the prior version. Replicas built this way could fail. Restore now errors in this case unless set or type=time/type=lsn is specified.

@@ -38,11 +42,14 @@

Add compress-level range checking for each compress-type.

+ +

The compress-level range was 0-9 for every compress-type. This is the range for gz but a subset of what lz4 and zst allow. Each type now has its own range, e.g. -7 to 22 for zst.

+ @@ -91,6 +98,7 @@ + @@ -100,7 +108,10 @@ - + + + + @@ -109,6 +120,92 @@

Refactor common/ini module to remove callbacks and duplicated code.

+ + + + + + + + + + + + + + + +

Audit memory contexts returned from functions and fix leaks.

+
+ + + + + + + + + +

Improve libbacktrace implementation.

+
+ + + + + + +

Fix error detail output to stderr.

+
+ + + + + + + + + + + + +

Improve debug, check, and buffer macros.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Update LICENSE.txt and PostgreSQL copyright for 2023.

+
@@ -127,6 +224,8 @@

Add warning about enabling hierarchical namespace on Azure storage.

+ +

With hierarchical namespace enabled, Azure requires directories to be deleted separately and expire fails. The user guide now warns not to enable it.

@@ -142,6 +241,8 @@

Add replacement for linefeeds in monitoring example.

+ +

The monitoring example failed when info output contained a linefeed, e.g. in some error messages, because COPY converts \n to a linefeed that jsonb rejects. The example now replaces linefeeds before converting to jsonb.

@@ -159,6 +260,8 @@

Clarify target-action behavior on various versions.

+ +

The effect of pause depends on hot_standby and the version. With hot_standby=off, pause acts like shutdown on >= 12 and like promote on earlier versions.

@@ -170,6 +273,8 @@

Updates and clarifications to index page.

+ +

The section about other backup solutions not supporting parallel processing was no longer accurate and has been reworded. Other sections were updated for current terminology and clarity.

@@ -179,7 +284,50 @@

Add dark mode to the website.

+ +

The website uses dark colors when the browser prefers a dark color scheme.

+ + + + + + + +

Update RHEL user guide to PostgreSQL 11/12.

+
+
+ + + + + + + + + + + + + + + + + +

Improve unit tests and test tools.

+
+ + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2023/2.45.xml b/doc/xml/release/2020s/2023/2.45.xml index 046bd7813..6ec85ebfd 100644 --- a/doc/xml/release/2020s/2023/2.45.xml +++ b/doc/xml/release/2020s/2023/2.45.xml @@ -15,6 +15,8 @@

Skip writing recovery.signal by default for restores of offline backups.

+ +

On >= 12, recovery.signal makes fail to start when the backup was made offline with wal_level=minimal. Restore now skips writing it for offline backups unless type is set explicitly, e.g. for Point-in-Time Recovery from an offline backup made with a higher wal_level.

@@ -30,7 +32,7 @@ - + @@ -41,6 +43,7 @@ + @@ -51,6 +54,8 @@

Block incremental backup (BETA).

+ +

Block incremental stores only the parts of a file that changed since the prior backup instead of the entire file. Enable it with repo-block, which requires repo-bundle. The feature is in beta and also requires the beta option. Do not use it in production: the on-disk format will change before the GA release.

@@ -64,6 +69,8 @@

Keep only one all-default group index.

+ +

An option that does not apply, e.g. repo2-s3-key when repo2-type is not s3, could add a phantom repository that has only default values. Repository and indexes with only default values are now removed unless no other index remains.

@@ -81,6 +88,72 @@

Add pg-version-force option for fork integration.

+ + + + + + + + + +

Add internal manifest command.

+
+ + + + + + + + + + + + +

Use uncrustify for code formatting.

+
+ + + + + + + + + +

Improve error handling in build-code binary.

+
+ + + + + + +

Improve interface handling in storage module.

+
+ + + + + + + + + + + + +

Clean up code and comments.

+
+ + + + + + +

Update config.guess and config.sub to latest versions.

+
@@ -96,6 +169,8 @@

Add explicit instructions for upgrading between 2.x versions.

+ +

A new user guide section explains that upgrading between 2.x versions requires only installing the new binaries. Downgrading is also possible when no features unsupported by the older version were used.

@@ -104,7 +179,34 @@

Remove references to SSH made obsolete when TLS was introduced.

+ +

The help for repo-host, pg-host, and their port options no longer refers to SSH as the only remote protocol. Details about SSH compression were also removed.

+ + + + + + + +

Fix contributors in release notes.

+
+
+ + + + + + + + + + + +

Improve unit tests.

+
+
+
diff --git a/doc/xml/release/2020s/2023/2.46.xml b/doc/xml/release/2020s/2023/2.46.xml index c62ab96ef..37f90a6b0 100644 --- a/doc/xml/release/2020s/2023/2.46.xml +++ b/doc/xml/release/2020s/2023/2.46.xml @@ -17,6 +17,8 @@

Block incremental backup.

+ +

Block incremental stores only the parts of a file that changed since the prior backup, which saves space and time in diff and incr backups of large files. Enable it with repo-block, which requires repo-bundle.

@@ -29,6 +31,8 @@

SFTP support for repository storage.

+ +

Set repo-type=sftp and repo-sftp-host to store the repository on an SFTP server.

@@ -42,6 +46,8 @@

16 support.

+ +

Adds the catalog version and WAL magic number for 16.

@@ -56,6 +62,8 @@

Allow page header checks to be skipped.

+ +

The page header checks made while verifying page checksums can report false errors for encrypted pages. Set page-header-check=n to skip them. They are enabled by default.

@@ -70,13 +78,22 @@

Avoid chown() on recovery files during restore.

+ +

Restore skipped chown() for restored files that already had the right owner but not for the recovery files it writes. The Posix driver now also skips chown() when the owner is already correct.

+ + + + +

Add error retry detail for HTTP retries.

+ +

An error after HTTP retries now reports how many retries were made and for how long.

@@ -90,6 +107,86 @@

Improve internal manifest command.

+ + + + + + + + + + + + + + + +

Improve object and allocation handling.

+
+ + + + + + + + + + +

Refactor the lock and configuration load modules.

+
+ + + + + + +

Sleep using nanosleep() instead of select().

+
+ + + + + + + + + +

Autogenerate PostgreSQL versions.

+
+ + + + + + + + + + + + +

Update modules to recent coding standards.

+
+ + + + + + + + + + + + + + + + +

Remove double spaces and extraneous whitespace.

+
@@ -105,6 +202,8 @@

Add warning about using recovery type=none.

+ +

Recovery type=none does not increment the timeline at the end of recovery, which can cause to archive duplicate WAL that is rejected and fills the disk, and can make tools like pg_rewind fail or corrupt the cluster. The documentation now warns against it.

@@ -113,7 +212,52 @@

Add note about running stanza-create on already-created repositories.

+ +

Stanzas that already exist are skipped, so stanza-create is safe to run again, e.g. after a new repository is configured.

+ + + + + + + + + + +

Update the user guide.

+
+
+ + + + + + + + + + + + + + +

Improve unit and integration tests.

+
+ + + + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2023/2.47.xml b/doc/xml/release/2020s/2023/2.47.xml index fb34302b0..9ef09ac37 100644 --- a/doc/xml/release/2020s/2023/2.47.xml +++ b/doc/xml/release/2020s/2023/2.47.xml @@ -15,6 +15,8 @@

Preserve block incremental info in manifest during delta backup.

+ +

When a file changed so that it would not use block incremental if it were new, e.g. it shrank below the block incremental limit or its timestamp moved far enough into the past, its block incremental info was lost from the manifest of a delta backup even though the file could still be referenced to the prior backup.

@@ -28,6 +30,8 @@

Fix block incremental file names in verify command.

+ +

The verify command used the compression extension instead of .pgbi for block incremental files stored outside a bundle, so it could not find them.

@@ -42,6 +46,8 @@

Fix spurious automatic delta backup on backup from standby.

+ +

File sizes on the standby can differ from the primary, e.g. for free space maps, so the next incremental backup could see a size change on the primary and switch to a checksum delta, which can take much longer. The original size is now kept in the manifest and used for the comparison.

@@ -55,6 +61,8 @@

Skip recovery.signal for >= 12 when recovery type=none.

+ +

With type=none, recovery.signal is no longer written for >= 12, which matches the behavior for earlier versions.

@@ -67,6 +75,8 @@

Fix unique label generation for diff/incr backup.

+ +

With at least two full backups and the latest expired, a diff or incr backup failed as if the clock had gone backward, because its label was compared with the label of the expired full backup.

@@ -79,6 +89,8 @@

Fix time-based archive expiration when no backups are expired.

+ +

When time-based retention was met but no backups were expired, archive was not expired and time-based archive retention not met was logged. One more backup was then needed to expire the earlier WAL.

@@ -97,6 +109,8 @@

Improve performance of SFTP storage driver.

+ +

The SFTP storage driver waited for a fixed time when libssh2 could not continue. It now waits until the socket can be read or written.

@@ -114,6 +128,8 @@

Add timezone offset to info command date/time output.

+ +

Timestamps in the info command output now include the timezone offset, so they can be used directly as a recovery target, e.g. with --target.

@@ -128,13 +144,64 @@

Centralize error handling for unsupported features.

+ +

Errors for features that were not compiled in, e.g. lz4, are now more detailed and consistent. Specifying SFTP storage when it was not compiled in no longer fails an assertion.

+ + + + + + + +

Use new LibXML error handler.

+
+ + + + + + +

Fix missed memory auditing in FUNCTION_LOG_RETURN_VOID().

+
+ + + + + + +

Increase protocolServerError() logging to debug level.

+
+ + + + + + +

Log when file size changes during backup.

+
+ + + + + + + + + + + +

Improve comments.

+
+
+ + @@ -144,5 +211,61 @@

Clarify preference to install from packages in the user guide.

+ + + + + + + + + + + + + + + + + +

Update the user guide, feature list, and NEWS.md.

+
+ + + + + + +

Build u20 image to speed contributing document generation.

+
+
+ + + + + + + + + + + + + +

Improve unit tests.

+
+ + + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2023/2.48.xml b/doc/xml/release/2020s/2023/2.48.xml index 3f9c45777..0d59f0b60 100644 --- a/doc/xml/release/2020s/2023/2.48.xml +++ b/doc/xml/release/2020s/2023/2.48.xml @@ -9,11 +9,12 @@ - - +

Fix issue restoring block incremental without a block list.

+ +

A block map with no blocks, which is written when a file timestamp changes but the file does not, was not decrypted when it followed a file stored without block incremental in the same bundle read. With enough affected files the retries were exhausted and the restore failed.

@@ -30,6 +31,8 @@

Add --repo-storage-tag option to create object tags.

+ +

Set repo-storage-tag to add tags to the objects written to an S3, GCS, or Azure repository. Tags are set for each repository.

@@ -42,6 +45,8 @@

Add known hosts checking for SFTP storage driver.

+ +

SFTP host keys are now checked against the known hosts files by default, i.e. repo-sftp-host-key-check-type=strict. Set repo-sftp-host-key-check-type=accept-new to add new hosts automatically, or repo-sftp-host-key-check-type=none to skip the check as before.

@@ -61,6 +66,8 @@

Support for dual stack connections.

+ +

Each address a host name resolves to is now tried in turn, e.g. an IPv6 address with no route to the host and then an IPv4 address, until one connects or the timeout expires. Repeated retry errors are also summarized in error messages.

@@ -73,6 +80,8 @@

Add backup size completed/total to info command JSON output.

+ +

The JSON output of the info command now includes the completed and total size of a backup in progress, so progress can be monitored by other programs.

@@ -86,6 +95,8 @@

Multi-stanza check command.

+ +

When stanza is not specified, the check command now checks every stanza in the configuration.

@@ -98,6 +109,8 @@

Retry reads of pg_control until checksum is valid.

+ +

On some filesystems, e.g. ext4, a read of pg_control during a concurrent write can return torn data. The read is now retried until the checksum is valid.

@@ -109,6 +122,8 @@

Optimize WAL segment check after successful backup.

+ +

The check for WAL segments after a backup listed the storage once for each segment. Each WAL directory is now listed once and the list is reused.

@@ -120,6 +135,8 @@

Improve GCS multi-part performance.

+ +

Chunks of a multi-part upload are now uploaded as soon as they are available.

@@ -131,6 +148,8 @@

Allow archive-get command to run when stanza is stopped.

+ +

The archive-get command does not write to the repository, so it can now run while the stanza is stopped, as restore can.

@@ -142,6 +161,8 @@

Accept leading tilde in paths for SFTP public/private keys.

+ +

Paths for repo-sftp-private-key-file and repo-sftp-public-key-file may now begin with ~, as documented.

@@ -154,6 +175,8 @@

Reload GCS credentials before renewing authentication token.

+ +

The service key file is now read again before the authentication token is renewed, so the key can be replaced while a command is running.

@@ -168,6 +191,71 @@

Add report option to check command.

+ + + + + + +

Update config.guess and config.sub to latest versions.

+
+ + + + + + +

Update xxHash to v0.8.2.

+
+ + + + + + + + + + + + + + + +

Clean up code.

+
+ + + + + + +

Finalize catalog number for PostgreSQL 16 release.

+
+ + + + + + +

Add prefix to meson build target to avoid conflicts.

+
+ + + + + + +

Fix manifest command filter for files in a tablespace.

+
+ + + + + + +

Add block incremental info to restore detail logging.

+
@@ -182,6 +270,8 @@

Fix configuration reference example for the tls-server-address option.

+ +

The example ::* was not valid. Use * for IPv4 or :: for IPv6.

@@ -192,6 +282,24 @@

Fix command reference example for the filter option.

+ + + + + + + +

Split release notes into individual files.

+
+ + + + + + +

Update help title for the --annotation option.

+
+
@@ -209,5 +317,30 @@

Allow storage/sftp unit test to run without libssh2 installed.

+ + + + + + + + + + + +

Improve unit tests.

+
+ + + + + + + + + +

CI updates.

+
+
diff --git a/doc/xml/release/2020s/2023/2.49.xml b/doc/xml/release/2020s/2023/2.49.xml index d629b9e26..fa1988065 100644 --- a/doc/xml/release/2020s/2023/2.49.xml +++ b/doc/xml/release/2020s/2023/2.49.xml @@ -19,6 +19,8 @@

Fix regression in retries.

+ +

v2.48 dropped the retry that was made when an operation used up its whole timeout, so a timeout became an error, e.g. waiting for a socket to be writable on an object store. Two retries are now made even when the timeout has expired.

@@ -32,6 +34,8 @@

Fix recursive path remove in SFTP storage driver.

+ +

Some SFTP servers report permission denied instead of a failure when a directory is unlinked as a file, so removing a path recursively failed on those servers.

@@ -45,6 +49,8 @@

Remove support for PostgreSQL 9.3.

+ +

9.3 is no longer supported, per the policy of supporting five end-of-life versions of .

@@ -59,6 +65,25 @@

Fix storageReadRemote() to return actual read bytes.

+ + + + + + +

Update config.guess and config.sub to latest versions.

+
+ + + + + + + + + +

Clean up code.

+
@@ -73,6 +98,8 @@

Document maintainer options.

+ +

Maintainer options are now documented in their own section with the caveats for using them, and pg-version-force is no longer internal.

@@ -81,6 +108,8 @@

Update point-in-time recovery documentation for >= 13.

+ +

Since 13 recovery errors when the recovery target is not reached. The point-in-time recovery section now works for 13 and later as well as for earlier versions.

@@ -95,8 +124,31 @@ + + + +

Build command and configuration reference in C.

+ + + + + + + + + +

Update the site introduction and the user guide.

+
+ + + + + + +

Update Minio test/documentation container version.

+
@@ -127,6 +179,32 @@

Remove unused fields from backupJobResult() test in command/backup unit.

+ + + + + + + + + + + + + + +

Improve unit tests.

+
+ + + + + + + + +

Add test to show behavior of bundled files truncated during backup.

+
diff --git a/doc/xml/release/2020s/2024/2.50.xml b/doc/xml/release/2020s/2024/2.50.xml index 30f573caf..9c424cbdb 100644 --- a/doc/xml/release/2020s/2024/2.50.xml +++ b/doc/xml/release/2020s/2024/2.50.xml @@ -11,11 +11,12 @@ - - +

Fix short read in block incremental restore.

+ +

A compressed super block can end with bytes that are not needed to decompress it but mark the end of the data. Depending on how a buffer lined up with the data, these bytes were not read and the restore failed.

@@ -30,6 +31,8 @@

Fix overflow suppressing backup progress in info output.

+ +

The sizes in the lock file were read as 32-bit values, so the info command did not report progress for a backup larger than 4GiB.

@@ -43,6 +46,8 @@

Preserve partial files during block incremental delta restore.

+ +

A file smaller than expected was not kept for a block incremental delta restore, although its blocks can be reused, e.g. when retrying a restore that failed or restoring over a smaller file.

@@ -54,6 +59,8 @@

Add support for alternate compile-time page sizes.

+ +

can be built with a different page size, e.g. 4096, and forks such as Greenplum do this.

@@ -69,6 +76,8 @@

Skip files truncated during backup when bundling.

+ +

A file truncated to zero after the files were assigned to bundles was still stored in its bundle, and a debug build failed an assertion. These files are now skipped.

@@ -99,6 +108,81 @@

Refactor backup incremental manifest generation.

+ + + + + + + + + +

Refactor backup and retry code.

+
+ + + + + + + + + +

Improve logging of file size changes and resume warnings during backup.

+
+ + + + + + + + + + + +

Fix comments.

+
+ + + + + + +

Update LICENSE.txt and PostgreSQL copyright for 2024.

+
+ + + + + + + + + + + + + + + + +

Improve unit tests.

+
+ + + + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2024/2.51.xml b/doc/xml/release/2020s/2024/2.51.xml index 93db042bc..5578ed17b 100644 --- a/doc/xml/release/2020s/2024/2.51.xml +++ b/doc/xml/release/2020s/2024/2.51.xml @@ -13,6 +13,8 @@

Skip zero-length files for block incremental delta restore.

+ +

An existing zero-length file caused a block incremental delta restore to fail in the block checksum filter. These files are now skipped, since there is nothing in them to reuse.

@@ -26,6 +28,8 @@

Fix performance regression in storage list.

+ +

Listing a path requested detailed information for each file, which could be slow, e.g. on object stores. Only the information the list needs is now requested.

@@ -54,6 +58,8 @@

Improved support for dual stack connections.

+ +

When a host name resolves to more than one address, e.g. IPv4 and IPv6, the next address is tried once the prior address has had reasonable time to connect, following the happy eyeballs approach of RFC 8305. A connection attempt that neither fails nor connects no longer uses up all the available time.

@@ -70,6 +76,8 @@

Make meson the primary build system.

+ +

meson is now the build system used for testing and for building the documentation. Functions not used outside their module are now hidden, which makes the binary smaller.

@@ -81,6 +89,8 @@

Detect files that have not changed during non-delta incremental backup.

+ +

During a non-delta diff or incr backup, a file that fits in a single buffer, or any block incremental file, is compared to the file in the prior backup and referenced instead of stored when it has not changed.

@@ -92,6 +102,8 @@

Prevent invalid recovery when backup_label removed.

+ +

When backup_label is removed from a restored cluster, uses the checkpoint in pg_control for crash recovery, which nearly always corrupts the cluster. Restore now invalidates the checkpoint in pg_control, so recovery fails instead. pg_controldata shows the checkpoint as 0/DEAD.

@@ -103,6 +115,8 @@

Improve archive-push WAL segment queue handling.

+ +

The size of every WAL segment in the queue was read to measure the queue. The size of the first segment is now used for all of them.

@@ -115,6 +129,8 @@

Limit resume functionality to full backups.

+ +

Resume did not work correctly for delta diff and incr backups, and a file that changed since the prior backup is likely to change again before a resume. Only full backups are resumed now.

@@ -126,6 +142,8 @@

Update resume functionality for block incremental.

+ +

Resume removed block incremental files, so it worked but copied all of them again. Block incremental files are now kept on resume.

@@ -138,6 +156,8 @@

Allow --version and --help for version and help.

+ +

--version and --help now work as they do for most programs. Use help for help on a specific command or option.

@@ -149,6 +169,8 @@

Add detailed backtrace to autoconf/make build.

+ +

Error stack traces in the autoconf/make build now include detail from libbacktrace, which performance tests showed has no noticeable cost.

@@ -163,6 +185,52 @@

Improve sort comparators.

+ + + + + + +

Fix help not displaying help for the help command.

+
+ + + + + + +

Update config.guess and config.sub to latest versions.

+
+ + + + + + + + + +

Improve asserts.

+
+ + + + + + + + + +

Validate more fields in pg_control.

+
+ + + + + + +

Redact secure options in check --report.

+
@@ -178,7 +246,68 @@

Update references to recovery.conf.

+ +

References to recovery.conf now include postgresql.auto.conf, which newer versions of use.

+ + + + + + + +

Migrate man page generation to C.

+
+ + + + + + +

Add release instructions to update PostgreSQL ecosystem wiki.

+
+
+ + + + + + + + + + + + +

Migrate integration tests to C.

+
+ + + + + + + + + + + + +

Improve unit tests and test tools.

+
+ + + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2024/2.52.1.xml b/doc/xml/release/2020s/2024/2.52.1.xml index ab716523e..e71c524b7 100644 --- a/doc/xml/release/2020s/2024/2.52.1.xml +++ b/doc/xml/release/2020s/2024/2.52.1.xml @@ -15,6 +15,8 @@

Fix issue with files larger on the replica than on the primary.

+ +

With block incremental, when a file was a different size on the primary than on the standby during a backup from standby, the next diff or incr backup stored the size from the primary. The backup after that failed with repo size must be > 0.

diff --git a/doc/xml/release/2020s/2024/2.52.xml b/doc/xml/release/2020s/2024/2.52.xml index dbe36019c..5c6ee0d81 100644 --- a/doc/xml/release/2020s/2024/2.52.xml +++ b/doc/xml/release/2020s/2024/2.52.xml @@ -14,6 +14,8 @@

Add GCS batch delete support.

+ +

Files are removed with batch requests instead of one request per file, which speeds up expire and other commands that remove files from the repository.

@@ -27,6 +29,8 @@

S3 SSE-C encryption support.

+ +

Set repo-s3-sse-customer-key to have S3 encrypt the data with the provided key after it is transmitted. This is not as secure as encrypting the data before it is transmitted with repo-cipher-type.

@@ -40,6 +44,8 @@

PostgreSQL 17beta1 support.

+ +

Adds the catalog version and WAL magic number for 17.

@@ -53,6 +59,8 @@

Allow explicit disabling of optional dependencies in meson builds.

+ +

An optional feature can be disabled in the meson build even when its library is installed, as some platforms require, e.g. FreeBSD. By default a feature is enabled when its library is found.

@@ -67,6 +75,8 @@

Dynamically find python in meson build.

+ +

The meson build now finds the python installation instead of requiring a python3 binary on the path, e.g. when only python3.9 is installed. The minimum meson version is now 0.47.

@@ -92,6 +102,46 @@

Update Fedora test image to Fedora 38.

+ + + + + + + + + + + + + +

Update modules to recent coding standards.

+
+ + + + + + + + + +

Silence Coverity complaints.

+
+ + + + + + + + + + + + +

Clean up code and comments.

+
@@ -110,5 +160,48 @@

Update start/stop documentation to reflect actual functionality.

+ + + + + + + + + + + +

Update the contributors, release notes, and metrics report.

+
+
+ + + + + + + + + + + + + +

Improve unit tests.

+
+ + + + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2024/2.53.1.xml b/doc/xml/release/2020s/2024/2.53.1.xml index a075b7ad2..9b3cd020e 100644 --- a/doc/xml/release/2020s/2024/2.53.1.xml +++ b/doc/xml/release/2020s/2024/2.53.1.xml @@ -12,6 +12,8 @@

Fix permissions when restore run as root user.

+ +

When restore was run as root, pg_control was owned by root. A restore as root also failed when the base path did not exist.

@@ -25,6 +27,8 @@

Fix segfault on delayed connection errors.

+ +

A connection error that was delayed long enough to be reported on a later wait could cause a segfault.

@@ -38,17 +42,45 @@

Skip local repository duplicate check for SFTP.

+ +

The check for local repositories that are configured more than once was also applied to SFTP repositories, which are never local.

+ +

PostgreSQL 17 support.

+ +

17beta3 changed the control and WAL formats, which is unusual for a beta.

+ + + + + + + +

Do not allow help for command roles other than main.

+
+
+ + + + + + + + +

Fix typo in user guide.

+
+
+
diff --git a/doc/xml/release/2020s/2024/2.53.xml b/doc/xml/release/2020s/2024/2.53.xml index 54fe2e52d..349b958f5 100644 --- a/doc/xml/release/2020s/2024/2.53.xml +++ b/doc/xml/release/2020s/2024/2.53.xml @@ -19,6 +19,8 @@

Fix SFTP renaming failure when file already exists.

+ +

Some SFTP servers report that a file already exists with an error that was not handled, so renaming a file over an existing file failed.

@@ -39,6 +41,8 @@

Allow backups to run concurrently on different repositories.

+ +

Backups of the same stanza can now run at the same time on different repositories, since locks are now per stanza and repository instead of per stanza. This is not possible for <= 9.5.

@@ -51,6 +55,8 @@

Support IP-based SANs for TLS certificate validation.

+ +

Certificates with an IP address as the subject alternative name, e.g. IP:1.2.3.4, are now validated. IPv4 and IPv6 addresses must match exactly.

@@ -65,6 +71,8 @@

Default log-level-stderr option to off.

+ +

Warnings and errors written to stderr were often lost when only stdout was redirected while collecting logs. An explicitly set log-level-stderr is not affected.

@@ -78,6 +86,8 @@

Allow alternative WAL segment sizes for PostgreSQL &le; 10.

+ +

<= 10 can be built with a different WAL segment size, and forks such as Greenplum set it with initdb.

@@ -91,8 +101,102 @@

Add hint to check SFTP authorization log.

+ +

When SFTP authentication fails the error now hints that the authorization log on the server may have more detail.

+
+ + + + + + +

Display time option defaults and allowed values with appropriate units.

+ +

Time option defaults and allowed values were shown in seconds, which was hard to read for large values. Fractional seconds are no longer allowed, so a value such as archive-timeout=0.5 must be written as archive-timeout=500ms.

+
+ + + + + + + + +

Require OpenSSL >= 1.1.1.

+ + + + + + + + + + +

Require the lz4 library and compiler builtins in the meson build.

+
+ + + + + + + + + + +

Improve option units, defaults, and error messages.

+
+ + + + + + + + + + + +

Improve option and command parsing.

+
+ + + + + + + + + +

Improve reading lock files in the info and stop commands.

+
+ + + + + + + + + + +

Refactor the backup and manifest code.

+
+ + + + + + + + + +

Fix formatting.

+
+
@@ -106,7 +210,62 @@

Clarify archive-push multi-repo behavior.

+ +

When one repository is failing, archive-push cannot push ahead to the other repositories unless archive-async is enabled.

+ + + + + + + + + + + + +

Update the contributing documentation and the documentation and test tools.

+
+
+ + + + + + + + + + + + + +

Migrate coverage testing to C and remove dependency on lcov.

+
+ + + + + + + + + + + + +

CI updates.

+
+
+
+ + + + + + + diff --git a/doc/xml/release/2020s/2024/2.54.0.xml b/doc/xml/release/2020s/2024/2.54.0.xml index 6416536a1..d55e43d80 100644 --- a/doc/xml/release/2020s/2024/2.54.0.xml +++ b/doc/xml/release/2020s/2024/2.54.0.xml @@ -19,11 +19,12 @@ - - +

Fix query performance for large datasets.

+ +

The query timeout logic delayed reading query results, which could make a query that returned a large result take up to db-timeout. Results are now read as soon as they are available.

@@ -38,6 +39,8 @@

Allow repositories on versioned storage to be read at a target time.

+ +

The archive-get, info, repo-get, repo-ls, restore, and verify commands can read a repository on versioned Azure, GCS, or S3 storage as it was at repo-target-time. This allows recovery even when the repository has been deleted or corrupted, accidentally or maliciously.

@@ -49,6 +52,8 @@

Allow requested standby backup to proceed with no standby.

+ +

Set backup-standby=prefer to back up from a standby when one is available and from the primary otherwise. This does not help when the standby responds but fails to sync with the primary after the backup starts.

@@ -62,6 +67,8 @@

Summarize backup reference list for info command text output.

+ +

The backup reference list can be very long, so the text output of the info command now summarizes it. The full list is shown when --set is specified.

@@ -74,6 +81,8 @@

Refresh web-id token for each S3 authentication.

+ +

The token file named by AWS_WEB_IDENTITY_TOKEN_FILE was read once at startup, so the token could expire during a long operation. The token is now read for each authentication.

@@ -85,6 +94,8 @@

Correctly display current values for indexed options in help.

+ +

The current value shown for an indexed option was always the value for the first index, e.g. pg1-path. The option help now lists the value for each index, and the option list shows <multi> when there is more than one.

@@ -96,10 +107,17 @@

Save backup.info only when contents have changed.

+ +

expire saved backup.info even when it had not changed. Fewer saves also make it easier to choose a target time on versioned storage.

- + + + + + + @@ -107,6 +125,8 @@

Remove limitation on reading files in parallel during restore.

+ +

The protocol could only read or write one file at a time on a remote, so a restore read one file at a time from the repository. Protocol commands can now be multiplexed, so a restore can read more than one file at a time, e.g. a bundle and the block incremental data for a file in it.

@@ -118,19 +138,54 @@

Improve SFTP error messages.

+ +

SFTP errors were reported as numbers only. They now include a description of the error.

- + + + + - -

Protocol command multiplexing.

+

Refactor config parsing and the help and version commands.

+
+ + + + + + + + + + + + + +

Refactor the storage and protocol modules.

+
+ + + + + + +

Finalize catalog number for PostgreSQL 17 release.

+
+ + + + + + +

Retry socket bind.

@@ -146,6 +201,8 @@

Add performance tuning section to user guide.

+ +

The options that commonly improve performance were spread through the documentation. The quickstart now has a section that lists them.

@@ -161,6 +218,8 @@

Clarify source for data_directory.

+ +

pg-path should match the data_directory reported by , which may differ from the value in postgresql.conf.

@@ -172,7 +231,80 @@

Better logic for deciding when a summary should be lower-cased.

+ +

Summaries that start with a proper name or an acronym, e.g. , are no longer lower-cased in the documentation.

+ + + + + + + + + + + +

Update documentation.

+
+ + + + + + + + + +

Improve documentation build.

+
+
+ + + + + + + + + + + + + + + + +

Improve test harness and unit tests.

+
+ + + + + + + + + + + + +

CI updates.

+
+
+
+ + + + + + + + + + + + diff --git a/doc/xml/release/2020s/2024/2.54.1.xml b/doc/xml/release/2020s/2024/2.54.1.xml index cdc4080ee..f02c005a1 100644 --- a/doc/xml/release/2020s/2024/2.54.1.xml +++ b/doc/xml/release/2020s/2024/2.54.1.xml @@ -13,10 +13,42 @@

Fix issue with version/help commands attempting to load pgbackrest.conf.

+ +

In v2.54.0 the version and help commands loaded pgbackrest.conf and failed when it could not be read or parsed.

+ + + + + + + + + + + +

Exclude logging macros from coverage reporting and fix volatile qualifiers.

+
+
+ + + + + + + + + + + +

Update documentation and release notes.

+
+
+
+ @@ -29,7 +61,23 @@

Stabilize async archiving in integration tests.

+ +

An async archive-get left running by one integration test could write an error to the queue of the next test and fail its recovery.

+ + + + + + + + + + + +

Update CI and integration tests.

+
+
diff --git a/doc/xml/release/2020s/2025/2.54.2.xml b/doc/xml/release/2020s/2025/2.54.2.xml index 791555d2a..64ad9dd06 100644 --- a/doc/xml/release/2020s/2025/2.54.2.xml +++ b/doc/xml/release/2020s/2025/2.54.2.xml @@ -10,8 +10,20 @@

Fix issue after disabling bundling with block incremental enabled.

+ +

When bundling was disabled after backups were made with bundling and block incremental enabled, the prior backups could not be read. The setting needed to read them is now preserved.

+ + + + + + + +

Update LICENSE.txt and PostgreSQL copyright for 2025.

+
+
@@ -24,7 +36,34 @@

Clarify behavior of multiple configuration files.

+ +

Each configuration file must be valid on its own, so a section must be specified in each file that sets an option in it. The documentation also notes that quoting is not supported, whitespace is trimmed from keys and values, and repeated sections are merged.

+ + + + + + + +

Clarify that unhandled errors may occur in edge cases.

+
+
+ + + + + + + + + + + +

Update CI and integration tests.

+
+
+
diff --git a/doc/xml/release/2020s/2025/2.55.0.xml b/doc/xml/release/2020s/2025/2.55.0.xml index 5b14af295..088f54977 100644 --- a/doc/xml/release/2020s/2025/2.55.0.xml +++ b/doc/xml/release/2020s/2025/2.55.0.xml @@ -9,11 +9,12 @@ - - +

Fix block incremental restore issue on non-default repository.

+ +

When the backup being restored used block incremental and was not in the lowest numbered repository, the restore read part of the block incremental data from the lowest numbered repository. Setting repo worked around the problem.

@@ -25,6 +26,8 @@

Do not set recovery_target_timeline=current for PostgreSQL &lt; 12.

+ +

Before 12, explicitly setting recovery_target_timeline to current behaves as latest, although current is the default. The setting is now left out of recovery.conf when it is set to current for these versions.

@@ -38,6 +41,8 @@

Fix expire archive range logging.

+ +

Only the last archive path removed was logged as the start of the range, so the log suggested that far fewer files were expired than were.

@@ -50,6 +55,8 @@

Fix error reporting for queries with no results.

+ +

An error from a query that expected no results was reported as an unexpected result instead of as the error.

@@ -63,9 +70,12 @@

Verify recovery target timeline.

+ +

A backup that cannot follow the target timeline, e.g. one made after a standby was promoted and the new timeline forked off, failed only when recovery started, with a error that is hard to interpret. The timeline is now checked against the history files before the restore starts.

+ @@ -74,6 +84,8 @@

Allow verification of a specified backup.

+ +

The verify option --set verifies only the specified backup and the WAL required to make it consistent.

@@ -90,6 +102,8 @@

Add support for S3/GCS requester pays.

+ +

Set repo-s3-requester-pays or repo-gcs-user-project to bill the requester instead of the bucket owner, e.g. so a hosted service can give customers access to their backups.

@@ -103,6 +117,8 @@

PostgreSQL 18 support.

+ +

This release was made before 18 had a beta, so support was initially experimental. Nothing that affects changed before 18.0.

@@ -112,11 +128,12 @@ - - +

Allow connections to on abstract domain sockets.

+ +

pg-socket-path no longer has to be an absolute path, so it can name an abstract domain socket. libpq reports a path that is not valid.

@@ -129,12 +146,17 @@

Add numeric output to version command.

+ +

Set --output=num to output the version as a number, e.g. 2055000, which is easier to compare.

- + + + + @@ -142,6 +164,8 @@

Allow backup command to operate on remote repositories.

+ +

The backup command can now run on a host where the repository is remote, which allows more flexibility in where backups are run.

@@ -156,6 +180,8 @@

Use lz4 for protocol compression.

+ +

lz4 compresses much faster than gz and gives similar ratios at the low levels used for protocol compression. Setting compress-level-network=0 no longer disables protocol compression.

@@ -167,6 +193,8 @@

Calculate content-md5 on S3 only when required.

+ +

The content-md5 header is only calculated for batch delete requests, which require it, to save CPU when files are uploaded. This change was reverted in v2.55.1.

@@ -180,6 +208,8 @@

Warn when a value for a multi-key option is overwritten.

+ +

Options with key/value pairs, e.g. recovery-option, silently overwrote a value when its key was specified again. A warning is now logged.

@@ -195,6 +225,8 @@

Add detail logging for expired archive path.

+ +

Removing a large number of archive files could look like a hang. A message at detail level now shows progress.

@@ -206,6 +238,8 @@

Remove support for PostgreSQL 9.4.

+ +

9.4 is no longer supported, per the policy of supporting five end-of-life versions of . Backups of 9.4 clusters can still be expired.

@@ -217,6 +251,8 @@

Remove autoconf/make build.

+ +

v2.54.0 was the last release to support the autoconf/make build. Use meson to build.

@@ -225,7 +261,7 @@ - + @@ -268,6 +304,129 @@

Remove extraneous const from cvtIntToZ() prototype.

+ + + + + + + + + + + + + + + + + + + + +

Enable additional compiler warnings.

+
+ + + + + + + + + + + +

Improve logging macros and their coverage.

+
+ + + + + + +

Allow negative values for integer options.

+
+ + + + + + + + + + +

Refactor the compression and protocol modules.

+
+ + + + + + +

Update LICENSE.txt and PostgreSQL copyright for 2025.

+
+ + + + + + + + + +

Separate version into component parts.

+
+ + + + + + + + + + +

Add StringId linter.

+
+ + + + + + + + + + + + +

Refactor code to satisfy Coverity.

+
+ + + + + + + + +

Fix typos.

+
+ + + + + + + + + + + +

Clean up code.

+
@@ -285,6 +444,8 @@

Fix documentation for specifying multiple stanzas with tls-server-auth.

+ +

Multiple stanzas are specified for tls-server-auth as a comma-separated list. The documentation said to repeat the option.

@@ -296,9 +457,12 @@

Clarify incremental backup expiration.

+ +

The documentation implied that incremental backups are expired by count. It now explains how incremental backups are expired and that full backups count as differential backups for differential retention.

+ @@ -318,6 +482,8 @@

Add FAQ about exporting self-contained cluster.

+ +

The FAQ explains how to create a self-contained export of a cluster with a backup made with --archive-copy and restored with --type=none.

@@ -331,6 +497,8 @@

Caveat --tablespace-map-all regarding tablespace creation.

+ +

A tablespace created after the backup starts is not in the manifest, so tablespace-map-all cannot map it.

@@ -355,6 +523,8 @@

Change --process-max recommendation for object stores to --repo-bundle.

+ +

On object stores repo-bundle reduces the time spent creating files far more than process-max does, because fewer files are created.

@@ -366,10 +536,12 @@

Update unix_socket_directory to unix_socket_directories.

+ +

unix_socket_directory has not been valid since 9.2, so only unix_socket_directories is documented.

- + @@ -379,6 +551,8 @@

Recommend not placing spool-path within pg_xlog/pg_wal.

+ +

A spool path inside pg_xlog or pg_wal can cause problems for tools such as pg_rewind.

@@ -393,6 +567,26 @@

Fix instances of of of.

+ + + + + + + + + + + + + + + + + + +

Update and correct the documentation.

+
@@ -419,6 +613,52 @@

Fix tests, logging, and comments in unit tests.

+ + + + + + + + + + + + + + + + +

CI updates.

+
+ + + + + + + + + + + + +

Improve the integration and unit tests.

+
+ + + + + + + + + + + + + + diff --git a/doc/xml/release/2020s/2025/2.55.1.xml b/doc/xml/release/2020s/2025/2.55.1.xml index c71f71552..a82b90a1b 100644 --- a/doc/xml/release/2020s/2025/2.55.1.xml +++ b/doc/xml/release/2020s/2025/2.55.1.xml @@ -12,6 +12,8 @@

Revert calculate content-md5 on S3 only when required.

+ +

S3 requires either content-md5 or an x-amz-content-* checksum for uploads when object lock is enabled, and Scality did not accept the alternate checksums, so uploads failed. content-md5 is calculated for all requests with content again.

@@ -26,7 +28,21 @@

Fix lower bounds checking for option keys.

+ +

An indexed option with a key of 0, e.g. pg0-path, caused a segfault. It is now an error.

+ + + + + + + + +

Add details about notifying packagers to release instructions.

+
+
+
diff --git a/doc/xml/release/2020s/2025/2.56.0.xml b/doc/xml/release/2020s/2025/2.56.0.xml index d6bb03732..a43cd7319 100644 --- a/doc/xml/release/2020s/2025/2.56.0.xml +++ b/doc/xml/release/2020s/2025/2.56.0.xml @@ -12,6 +12,8 @@

Fix issue with adhoc expiration when no backups in a repository.

+ +

Adhoc expiration failed with cannot get index 0 from list with 0 value(s) when a repository had no backups.

@@ -27,6 +29,8 @@

Add restore progress to info command output.

+ +

The restore command now records its progress, which the info command reports alongside backup progress. A restore is also no longer terminated by the stop command.

@@ -39,6 +43,8 @@

Add progress-only detail level for info command output.

+ +

Set --detail-level=progress to report only progress, which is faster because the repository is not read. The default is full.

@@ -52,6 +58,8 @@

Retry failed reads on object stores.

+ +

A read from an object store that failed after it started was fatal, which could restart an expensive job, e.g. during restore. A failed read is now retried from where it left off.

@@ -64,6 +72,8 @@

Fix defaults in command-line help.

+ +

When an option has more than one default, e.g. repo-storage-upload-chunk-size with an S3 and an Azure repository, the option list shows <multi> and the help for the option lists each default. Defaults are not shown for options that are not valid in the current configuration.

@@ -78,6 +88,36 @@

Improve the predictability of floating point numbers formatted as strings.

+ + + + + + + + + + + + + + +

Improve option defaults and dependencies.

+
+ + + + + + + + + + + + +

Clean up code.

+
@@ -92,6 +132,8 @@

Describe discrete option values in a list where appropriate.

+ +

The values of options such as output for the verify and version commands are now described as a list, as for other options.

@@ -105,5 +147,59 @@

Fix less than in help output for archive-mode option.

+ + + + + + + + + + + + +

Update the contributing, release, and support documentation.

+
+
+ + + + + + + + + + + + + + +

CI updates.

+
+ + + + + + + + + + + +

Improve unit tests.

+
+
+
+ + + + + + + + diff --git a/doc/xml/release/2020s/2025/2.57.0.xml b/doc/xml/release/2020s/2025/2.57.0.xml index 239435a30..89786654e 100644 --- a/doc/xml/release/2020s/2025/2.57.0.xml +++ b/doc/xml/release/2020s/2025/2.57.0.xml @@ -11,6 +11,8 @@

Unnest HTTP/TLS/socket timeouts.

+ +

A failed socket connection was also retried by the TLS and HTTP layers, so with the default io-timeout of 60 seconds a connection took nine minutes to time out. Each layer now retries only its own failures.

@@ -22,6 +24,18 @@

Fix possible segfault in page checksum error message.

+ +

The error message for invalid page checksums used a string that was out of scope, which could log garbage or crash. This was most likely with pg_tde, since every encrypted file fails the page checksum.

+
+ + + + + + +

Fix possible segfault in backup resume messages.

+ +

The message that reports why a backup cannot be resumed used a string that was out of scope, which could log garbage or crash.

@@ -37,6 +51,8 @@

Add repo-symlink option to suppress creation of repository symlinks.

+ +

Some filesystems that are otherwise Posix-compatible do not support symlinks. Set repo-symlink=n to keep the latest and tablespace symlinks from being created in the repository.

@@ -50,7 +66,74 @@

Add HTTP retries for 408 and 429 errors.

+ +

HTTP 408 (Request Timeout) and 429 (Too Many Requests) errors are now retried. 429 errors are common on Cloudflare R2.

+ + + + + + + + + + +

Finalize catalog number for PostgreSQL 18 release.

+
+ + + + + + + + + + +

Remove unused code and fix comments.

+
+
+ + + + + + + + +

Update user guide and tests to Ubuntu 22.04.

+
+
+
+ + + + + + + + + + + + + +

CI updates.

+
+ + + + + + + + + +

Clean up unit tests.

+
+
+
diff --git a/doc/xml/release/2020s/2026/2.58.0.xml b/doc/xml/release/2020s/2026/2.58.0.xml index 227234b2a..d905f2f7e 100644 --- a/doc/xml/release/2020s/2026/2.58.0.xml +++ b/doc/xml/release/2020s/2026/2.58.0.xml @@ -15,6 +15,8 @@

Fix deadlock due to logging in signal handler.

+ +

A signal that arrived while a lock was held by gmtime_r(), e.g. the SIGTERM sent by stop with --force, could deadlock when the signal handler logged. The signal handler now logs with only async-signal-safe functions.

@@ -29,6 +31,8 @@

HTTP support for S3, GCS, and Azure.

+ +

An object store endpoint can now begin with http:// to connect without TLS. HTTPS is still used when the endpoint does not specify a protocol.

@@ -42,6 +46,8 @@

Allow expiration of oldest full backup regardless of current retention.

+ +

The expire option --oldest expires the oldest full backup and the backups that depend on it regardless of the retention settings, e.g. when the repository is running out of space. WAL before the oldest remaining full backup is expired as well.

@@ -55,6 +61,8 @@

Support for Azure managed identities.

+ +

Set repo-azure-key-type=auto to fetch credentials automatically using managed identities instead of configuring them. The credentials are refreshed before they expire.

@@ -69,6 +77,8 @@

Experimental support for S3 EKS pod identity.

+ +

Set repo-s3-key-type=pod-id to fetch credentials automatically using EKS pod identity instead of configuring them. The credentials are refreshed before they expire.

@@ -84,6 +94,8 @@

Allow configuration of TLS cipher suites.

+ +

Set tls-cipher-12 for TLS 1.2 and tls-cipher-13 for TLS 1.3, e.g. for compliance. The cipher suites apply to every connection a process makes.

@@ -95,6 +107,8 @@

Allow process priority to be set.

+ +

priority sets the scheduling priority of processes from -20 to 19, as with nice. A higher value makes less likely to interfere with .

@@ -108,6 +122,8 @@

Allow dots in S3 bucket names when using path-style URIs.

+ +

Dots in a bucket name only cause a certificate host name mismatch with host-style URIs, so they are now allowed with repo-s3-uri-style=path, which most self-hosted S3 services use.

@@ -120,6 +136,8 @@

Require TLS >= 1.2 unless verification is disabled.

+ +

TLS 1.0 and 1.1 have been deprecated since 2021. Verification is always enabled for connections between hosts. When verification is disabled for an object store with repo-storage-verify-tls, e.g. for a self-signed certificate, every protocol version is allowed.

@@ -133,6 +151,8 @@

Dynamically size S3/GCS/Azure chunks for large uploads.

+ +

The number of chunks in an upload is limited, so with the default repo-storage-upload-chunk-size the largest file that could be uploaded was 50GiB to S3, 40GiB to GCS, and 200GiB to Azure. The chunk size now grows during an upload, so files up to 5TiB can be uploaded to S3 and GCS and up to 45TiB to Azure.

@@ -144,6 +164,8 @@

Optimize S3/GCS/Azure chunk size for small files.

+ +

The whole chunk buffer was allocated when a file was opened, although many files are smaller than a chunk. The buffer now grows as data arrives, which saves memory when small files are uploaded.

@@ -155,6 +177,8 @@

Remove support for PostgreSQL 9.5.

+ +

9.5 is no longer supported, per the policy of supporting five end-of-life versions of .

@@ -167,8 +191,91 @@

Improve logging of default for options with an unresolved dependency.

+ +

An option set in the configuration file was logged at the start of a command when its dependency was not resolved, although its default value was used. The option is no longer logged in this case.

+ + + + + + + + + + + + + +

Simplify the versioned types.

+
+ + + + + + +

Use get_option() for tasks supported by the new meson version.

+
+ + + + + + + + + + + + + + + + + + +

Simplify the option definitions in config.yaml.

+
+ + + + + + +

Use JsonRead for all info JSON parsing.

+
+ + + + + + + + + + + + + + + +

Refactor StringId and option parsing.

+
+ + + + + + + + + + +

Fix logging, formatting, and comments.

+
+
@@ -182,6 +289,8 @@

Remove explicit max_wal_senders/wal_level configuration from user guide.

+ +

max_wal_senders and wal_level have defaulted to the values the user guide requires since 10.

@@ -193,7 +302,62 @@

Clarify that bundling is useful for filesystems with large block sizes.

+ +

Bundling saves space on filesystems with large block sizes, where each small file takes a whole block.

+ + + + + + + + + + + + + +

Improve the documentation build.

+
+ + + + + + + + + +

Improve wording in the user guide.

+
+
+ + + + + + + + +

Fix WAL segment numbering in command/expire unit test.

+
+ + + + + + + + + + + + +

CI updates.

+
+
+
diff --git a/doc/xml/release/2020s/2026/2.59.0.xml b/doc/xml/release/2020s/2026/2.59.0.xml index e2738933d..2bfcb4e42 100644 --- a/doc/xml/release/2020s/2026/2.59.0.xml +++ b/doc/xml/release/2020s/2026/2.59.0.xml @@ -20,6 +20,8 @@

Fix expire removing a backup in progress on another host.

+ +

A backup is not added to backup.info until it completes, so when expire ran on one host while a backup was running on another, e.g. expire on a standby while the primary is backed up, the backup in progress was removed. Expiration no longer removes the latest backup when it is in progress or resumable.

@@ -33,6 +35,8 @@

Fix archive-push-queue-max not enforced when a WAL file errors.

+ +

In asynchronous mode the queue was measured against the WAL yet to be pushed. When a WAL file errored repeatedly the WAL files after it were pushed and no longer counted, although they stayed in pg_wal, so the queue limit was never reached and pg_wal could fill the disk. The queue is now measured against all the WAL is waiting to archive, as in synchronous mode.

@@ -46,6 +50,8 @@

Fix async archive-get failure during recovery across a timeline switch.

+ +

Two async processes could race for the archive lock, and the one that lost exited before fetching the segment it was started for. The archive-get that started it then waited for archive-timeout and returned an error for a segment that exists, which could end recovery early, especially across a timeline switch. The segment is now fetched directly when the async process that should fetch it is not running.

@@ -59,6 +65,8 @@

Fix potential buffer overrun in error module.

+ +

A stack trace too long for its buffer was not terminated and could be read past the end of the buffer, and an error message too long for its buffer could write past the end of it when a system error was appended. Both require an unusually long message.

@@ -72,6 +80,8 @@

Fix use-after-free of parallel protocol client.

+ +

A client that ran out of work was freed but left in the client list and freed again on a later call. With debug or trace logging this read freed memory and could crash, e.g. a parallel backup with log-level-file=trace.

@@ -85,6 +95,20 @@

Fix heap overflow when a pg option is set without pg1.

+ +

When pg options were set for other indexes without pg1-path, e.g. pg2-path and pg3-path, the index map was overwritten. This corrupted the heap on musl, e.g. Alpine, and caused a segmentation fault. The highest numbered pg-path was also dropped.

+
+ + + + + + + + +

Fix crash when a signal arrives during exit on musl 1.2.6.

+ +

musl 1.2.6, e.g. on Alpine 3.24, crashes when exit() is called while an exit is already in progress. This happened when a signal arrived during exit, e.g. when the server command terminated a child process that was already exiting. A signal that arrives during exit is now ignored.

@@ -101,6 +125,8 @@

PostgreSQL 19beta2 support.

+ +

Adds support for 19beta2. 19 can enable and disable page checksums online, and page checksums are not validated while either is in progress.

@@ -115,6 +141,8 @@

Add archive-expire-before option to clean up WAL archive.

+ +

The expire option archive-expire-before removes WAL before a given segment from the archive but never WAL that a retained backup requires. It can clean up the archive from the restartpoint of a standby with archive_cleanup_command instead of pg_archivecleanup, which does not know about retention.

@@ -127,6 +155,8 @@

Add batch delete for Azure storage.

+ +

Files are removed with the Azure Blob Batch API, up to 256 per request, instead of one request per file. This speeds up expire and other commands that remove files from the repository.

@@ -139,6 +169,8 @@

Add support for S3 Outposts.

+ +

Set repo-s3-service=s3-outposts when using an S3 Outposts endpoint. The option sets the service name used for request signing and defaults to s3.

@@ -151,14 +183,29 @@

Add S3 process authentication.

+ +

Set repo-s3-key-type=process and set repo-s3-process-cmd to a command that outputs temporary credentials in the JSON format of the AWS process credential provider. The credentials are refreshed before they expire.

+
+ + + + + + +

Provide a distribution tarball with generated code and documentation.

+ +

The tarball includes the generated code and the rendered man page and HTML documentation, so it builds and installs without the code generation and documentation tooling, including libyaml.

- - - + + + + + + @@ -168,6 +215,8 @@

Reconnect SFTP storage after the server drops an idle connection.

+ +

SFTP servers and firewalls may drop a connection that has been idle for a while, e.g. the repository read connection during the copy phase of a backup, and the next use failed with a socket error. A dropped connection is now reopened and the operation is retried once.

@@ -179,6 +228,8 @@

Add user/group caching for faster manifest build.

+ +

When user and group names are looked up through a remote name service, e.g. sssd or LDAP, each lookup is a round trip, which dominated the manifest build for clusters with millions of files. User and group names are now cached.

@@ -192,6 +243,8 @@

Add per-repo backup progress to info command output.

+ +

When backups run on more than one repository at once, the info command now reports progress for each repository as well as overall progress. The JSON output has a repo array for each backup lock.

@@ -205,6 +258,8 @@

Add backup.info checks to verify command.

+ +

The verify command now warns when a backup in the repository is not in backup.info and when a backup in backup.info is missing from the repository. A missing backup is reported as having a missing manifest.

@@ -217,6 +272,8 @@

Allow the S3 STS endpoint to be configured.

+ +

Set repo-s3-sts-host to use a regional STS endpoint with repo-s3-key-type=web-id, e.g. sts.eu-central-2.amazonaws.com. AWS opt-in regions do not accept credentials from the global endpoint, which is still the default.

@@ -228,6 +285,8 @@

Add archive-push-batch-size to limit WAL pushed per asynchronous run.

+ +

In asynchronous mode archive-push-queue-max is only checked at the start of a run, so a run working through a large backlog could let the queue grow well past the limit. archive-push-batch-size (default 16GiB) limits the WAL pushed per run, so the queue is checked again sooner.

@@ -241,6 +300,8 @@

Exit async archive-push on first error.

+ +

When the repository was unavailable the async process kept trying every ready WAL segment, so a run could take long enough for pg_wal to fill before archive-push-queue-max was checked again. The run now exits on the first error, after the jobs in progress finish.

@@ -252,6 +313,8 @@

Harden HTTP chunked response parsing.

+ +

Chunk extensions and trailers are now accepted, transfer-encoding is compared without regard to case, and a response with both transfer-encoding and content-length is rejected.

@@ -264,6 +327,8 @@

Error when running as root unless allow-root is enabled.

+ +

Running a command other than restore as root could create files in the repository, e.g. backup.info, that the user cannot access. allow-root is disabled by default for every command except restore, and the check also applies on remote hosts.

@@ -275,6 +340,8 @@

Fewer binary searches when building manifest.

+ +

The manifest build for a diff or incr backup searched the prior manifest three times for each file. It now searches once, which saves millions of searches for clusters with millions of files.

@@ -287,6 +354,8 @@

Improve seek performance during block incremental delta restore.

+ +

A seek and a flush of the write buffer were done for every block written during a block incremental delta restore, and blocks are often 8KiB. The file position is now tracked and the seek and flush are only done when needed.

@@ -298,6 +367,8 @@

Bundle backup files in order rather than scanning for a better fit.

+ +

A file that would push a bundle over repo-bundle-size was skipped for a smaller file later in the queue. Files are now added in order and a bundle is closed once it reaches repo-bundle-size, so a bundle may exceed it by up to repo-bundle-limit.

@@ -311,6 +382,8 @@

Report the underlying error when a query fails to complete.

+ +

When the connection was lost after the first result of a query was delivered, e.g. under load, the error was the generic NULL result required to complete request. The error from is now reported, with hints about a lost connection and about aggressive idle_session_timeout and idle_in_transaction_session_timeout settings.

@@ -324,6 +397,8 @@

Report the actual error when an S3 credential request fails.

+ +

An error from AWS for a web-id or pod-id credential request was reported as a failure to parse the response. The error returned by AWS is now reported, and the tokens are redacted when the request is logged.

@@ -337,6 +412,8 @@

Report archive-push spool path errors to the PostgreSQL log.

+ +

When the async spool path could not be created, e.g. permission was denied, the error could not be written to the spool and archive-push failed with a generic timeout that pointed at the async log. The spool path is now created before the async process starts, so the error appears in the log.

@@ -345,6 +422,8 @@

Hint that pgBackRest may be out of date when a version is unsupported.

+ +

When does not recognize a version, e.g. an older on the restore host reading a backup of a newer cluster, the error now hints that may need to be updated on all hosts. The version is reported in user-facing form, e.g. 13 rather than 130000.

@@ -357,6 +436,8 @@

Add systemd notify integration.

+ +

When built with libsystemd, the server command notifies systemd when it is ready to accept connections and when it is stopping, as and PgBouncer do.

@@ -368,6 +449,8 @@

Suppress unused parameter errors in meson compiler probes.

+ +

The meson compiler probes declared main() parameters they did not use, which failed the probes when unused parameter warnings were errors.

@@ -394,6 +477,148 @@

Refactor restore module into included modules.

+ + + + + + +

Update LICENSE.txt and PostgreSQL copyright for 2026.

+
+ + + + + + +

Enhance StringId with optional sequence information.

+
+ + + + + + + + + + + + + +

Refactor the storage read and write interfaces.

+
+ + + + + + + + + + + + +

Improve error handling in the SFTP storage driver.

+
+ + + + + + + + + + +

Refactor the manifest module into included modules.

+
+ + + + + + +

Reverse sort order in backup and restore comparators.

+
+ + + + + + + + + +

Free memory sooner in restoreFile().

+
+ + + + + + +

Move archiveAsyncExec() to command/command module and rename.

+
+ + + + + + + + + + + +

Ban unsafe string functions and limit an oversized log message.

+
+ + + + + + + + + + + +

Improve code generation for the configuration and help.

+
+ + + + + + + + + + + + + + + + +

Improve compiler compatibility and build checks.

+
+ + + + + + + + + + + + +

Clean up code and comments.

+
@@ -408,6 +633,8 @@

Make stanza option internal for the repo-* commands.

+ +

The stanza option only has an effect on the repo-* commands with undocumented storage path constants, so the documentation implied it did something it does not. The option is no longer documented for these commands and works as before.

@@ -421,6 +648,8 @@

Document that info reads encryption settings from global section.

+ +

When run without stanza the info command reads encryption settings only from the global section, so encryption settings configured for a stanza require stanza.

@@ -434,6 +663,8 @@

Document that expire-auto uses the backup command configuration.

+ +

Automatic expiration after a backup uses the configuration of the backup command, so options set only for the expire command are not applied. Disable expire-auto and run expire separately when it needs its own configuration.

@@ -447,6 +678,8 @@

Document adjusting the logrotate su directive for a dedicated user.

+ +

Packages may install a logrotate configuration that rotates the logs as the postgres user. When a dedicated user owns the repository and logs, the su directive must be changed to that user or rotation fails with a permission error.

@@ -460,8 +693,76 @@

Document that end-of-line comments are not supported in config files.

+ +

End-of-line comments have never been supported, although they may appear to work for some options. Only comments on a line of their own are supported.

+ + + + + + + + + + + + + + + + + + +

Add the news page and sponsors to the website.

+
+ + + + + + + + + + + + + + + + +

Update and correct the documentation.

+
+ + + + + + + + + + + + + + +

Improve the documentation build.

+
+ + + + + + + + + +

Replace Minio with Ceph for S3 documentation and testing.

+
+
@@ -475,7 +776,100 @@

Fix Alpine group conflicts in CI containers.

+ +

Group entries with members are now handled when the test group is renamed, and the Alpine group is only created when it does not already exist.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

CI updates.

+
+ + + + + + + + + + + + + +

Add a smoke test to verify a build against installed PostgreSQL.

+
+ + + + + + + + + + + + + + + + + + + + +

Improve the test harness.

+
+ + + + + + + + + + + + + + + +

Improve unit tests.

+
+
diff --git a/doc/xml/release/2020s/2026/2.59.1.xml b/doc/xml/release/2020s/2026/2.59.1.xml index 9f20ba104..93aef3586 100644 --- a/doc/xml/release/2020s/2026/2.59.1.xml +++ b/doc/xml/release/2020s/2026/2.59.1.xml @@ -13,6 +13,8 @@

Fix hang when the chunk buffer is smaller than the input buffer.

+ +

A multi-part upload to S3, GCS, or Azure could loop forever when the chunk buffer was smaller than the input buffer, e.g. after the chunk size grew during the upload. The chunk buffer is now always large enough to hold the input buffer.

@@ -26,6 +28,8 @@

Compare a new backup label only against its own full backup set.

+ +

Some object stores keep listing a prefix after everything under it has been deleted, e.g. MinIO with object locking or SeaweedFS, so a full backup that was removed could still appear in the repository. Every diff and incr backup after it then failed with new backup label ... is not later than latest backup label .... A new label is now compared only against the backups in its own full backup set.

@@ -39,6 +43,8 @@

Fix source archives generated by GitHub missing files required to build.

+ +

The source archives GitHub generates for a release were missing the code generation tooling and the files it reads, so they could not be built. Only the distribution tarball is trimmed now.

@@ -50,6 +56,8 @@

PostgreSQL 19beta3 support.

+ +

19beta3 changed the WAL page magic number.

@@ -64,6 +72,8 @@

Document exception for dots in S3 bucket names when repo-s3-uri-style=path.

+ +

With repo-s3-uri-style=path the bucket is part of the path instead of the host name, so dots in the bucket name do not cause a certificate host name mismatch.

@@ -74,7 +84,19 @@

Remove explicit hot_standby configuration from user guide.

+ +

hot_standby has been enabled by default since 10. The quickstart now notes that a standby does not accept read-only connections without it.

+ + + + + + + +

Fix broken release link in news.xml.

+
+
diff --git a/doc/xml/release/2020s/2026/2.59.2.xml b/doc/xml/release/2020s/2026/2.59.2.xml index b1433df35..85ba3e036 100644 --- a/doc/xml/release/2020s/2026/2.59.2.xml +++ b/doc/xml/release/2020s/2026/2.59.2.xml @@ -12,6 +12,8 @@

Fix empty block map when file is truncated to zero during backup.

+ +

A block incremental file larger than repo-bundle-limit and truncated to zero by during a backup was stored as a block map with no blocks. Every later backup that referenced the file failed with unexpected eof until the next full backup.

@@ -25,6 +27,8 @@

Disable read retry when filters are passed to the driver.

+ +

A retried read from a repository on an object store, accessed through a repository host, crashed. These reads are no longer retried by the client. The repository host still retries its read from the object store.

@@ -39,6 +43,8 @@

Fix pagination of S3 version listing.

+ +

Reading a repository at a target time with repo-target-time failed with unable to find child 'NextContinuationToken' when more than a thousand versions were listed under a prefix.

@@ -52,6 +58,8 @@

Set the Azure version header for SAS authentication.

+ +

Batch deletes require the version header, so with SAS authentication every batch was rejected. The rejection looked like a single failed file, and the rest of each batch was not deleted while expire reported success, leaving expired backups and WAL in the repository.

@@ -65,6 +73,8 @@

Fix async archive-push stalling on a zero-size backup history file.

+ +

A zero-size backup history file, e.g. in a cluster copied from a storage snapshot, failed every asynchronous archive-push run, so no WAL was archived. archive-push-batch-size is now converted to a segment count using the size of the first ready WAL segment.

@@ -76,6 +86,8 @@

Fix annotate command on a remote encrypted repository.

+ +

When the repository was encrypted and the cipher was configured only on the repository host, annotate failed to load backup.info.

@@ -86,6 +98,8 @@

PostgreSQL 19beta4 support.

+ +

19beta4 reverted online page checksum changes, so the page checksum version is again limited to 0 and 1. It also changed the pg_control version and the WAL page magic number.

diff --git a/doc/xml/release/2020s/2026/2.59.3.xml b/doc/xml/release/2020s/2026/2.59.3.xml index 0b51ebb53..6dca362ce 100644 --- a/doc/xml/release/2020s/2026/2.59.3.xml +++ b/doc/xml/release/2020s/2026/2.59.3.xml @@ -15,6 +15,8 @@

Fix possible checksum error loading encrypted info and manifest files.

+ +

A large encrypted info or manifest file could lose its last lines when loaded, which failed the checksum. The lost lines had to fit in the final cipher block, so this is unlikely in practice.

@@ -29,6 +31,8 @@

Fix possible weak encryption subkeys/salts.

+ +

When OpenSSL could not get random data from the operating system the failure was ignored, and subkeys and salts were generated from memory that was not random. An error is now reported.

diff --git a/doc/xml/release/2020s/2026/2.60.0.xml b/doc/xml/release/2020s/2026/2.60.0.xml index 85ca215df..ed12588e4 100644 --- a/doc/xml/release/2020s/2026/2.60.0.xml +++ b/doc/xml/release/2020s/2026/2.60.0.xml @@ -19,6 +19,8 @@

Add checksum-page-error option to error on invalid page checksums.

+ +

This option applies to the backup, restore, and expire commands. The backup command defaults to a warning for each file (as before) and now also reports the total number of checksum warnings at the end of the backup. The restore and expire commands default to an error. Previously the restore command did not report invalid page checksums at all.

@@ -34,23 +36,17 @@

Support for GCS Workload Identity Federation.

-
- - - - - - - - - - -

Prefetch multi-file/range reads from object stores.

+

Set repo-gcs-key-type=web-id and set repo-gcs-key to an external account credential file, e.g. as generated by gcloud iam workload-identity-pools create-cred-config. The web identity token is exchanged for an access token without a service account key. The token file is reloaded on each exchange to pick up rotated tokens, e.g. Kubernetes projected service account tokens. Service account impersonation is not supported.

- + + + + + + @@ -58,7 +54,24 @@ -

Combine prior block incremental map reads during backup.

+

Prefetch multi-file/range reads from object stores.

+ +

Requests are queued ahead of the current read so requests proceed while reading, and small gaps between files are read over instead of starting a new request. Restore uses this to read bundled files and block incremental maps, and backup uses it to read block incremental maps from the prior backup. repo-storage-prefetch (default 3) sets how many requests are queued and repo-storage-read-over (default 64KiB) sets the largest gap that is read over.

+
+ + + + + + + + + + + +

Reduce keep-alive requests to remote processes.

+ +

A keep-alive was sent to every remote each time a job completed in archive-push and backup, even when the remotes had just been sent a request. A keep-alive is now sent only when no request has been sent to the remote for 30 seconds.

@@ -71,6 +84,8 @@

Retry Azure batch sub-requests missing from the response.

+ +

When Azure fails a batch delete it may return a single response for the entire batch. The sub-requests with no response were treated as complete, so only one file per batch was removed while the command reported success. Sub-requests with no response are now retried.

@@ -84,6 +99,8 @@

Reduce the manifest checks made when reconstructing backup.info.

+ +

The backup, expire, and annotate commands no longer check for a backup.manifest when the repository listing shows the backup path does not exist, or when a diff or incr backup belongs to a full backup set that is not in backup.info. Each check is a request so on an object store the check for a missing manifest is logged as a 404.

@@ -95,10 +112,17 @@

Use original size to determine if a file should be bundled.

+ +

The size of a block incremental file in the prior backup was used to decide whether to bundle it, so a file that had grown past repo-bundle-limit could still be stored in a bundle. The current size of the file is now used.

- + + + + + + @@ -107,6 +131,21 @@

Add context to block map read errors during backup.

+ +

An error reading the block map of a prior backup now reports the file, repository path, offset, and map size. A read that returns fewer bytes than expected is reported as such instead of as a parse error.

+
+ + + + + + + + + +

Cast current_timestamp to text in the backup start label.

+ +

A user-defined implicit cast from timestamptz to text caused the backup to fail with operator is not unique: unknown || timestamp with time zone. The label text is unchanged.

@@ -119,17 +158,48 @@

Support building on illumos.

+ +

An OmniOS job has been added to CI. Solaris may also work but has not been tested.

- + - - + + -

Cast current_timestamp to text in the backup start label.

+

Support OpenSSL 4.

+ +

Building against OpenSSL 4 failed because X509_get_subject_name() now returns a const name.

+
+ + + + + + + + + + + +

Fix clang builds.

+ +

On Linux, gcc installs libbacktrace.a where clang also looks for it but installs backtrace.h where only gcc can find it. A clang build found the library and then failed to compile. The library is now only used when its header is found. Return types that clang reports as narrowing conversions in debug builds are also fixed.

+
+ + + + + + + + +

Migrate code generation from C to Python.

+ +

Code is generated during the build from the option, error, help, and declarations by a Python tool instead of a C tool that had to be built first. Building from a git checkout requires PyYAML instead of libyaml. The release tarball includes the generated code and requires neither.

@@ -147,14 +217,16 @@ - + + + -

Derive the cipher key with SHA-256 at repository format 6

+

Derive the cipher key with SHA-256 for repository format 6.

@@ -214,15 +286,148 @@ - - + + - - + -

Allow test user names that adduser on Debian rejects.

+

Fix out-of-bounds reads found by Fil-C.

+
+ + + + + + + + + + + + + + + + + +

Fix bugs in the JSON and pack readers found by fuzzing.

+
+ + + + + + + + + + + +

Refactor the backup and restore modules into included modules.

+
+ + + + + + + + + + + + + + + + +

Remove unused parameters and struct members.

+
+ + + + + + + + + +

Check that block macros are closed by the macro that matches them.

+
+ + + + + + + + + + + + + + +

Improve code generation for the help and interfaces.

+
+ + + + + + + + + + + + + + +

Fix minor issues.

+
+ + + + + + +

Store the file owner as an index rather than a pointer in the pack.

+
+ + + + + + +

Increase the minimum meson version to 0.55.3.

+
+ + + + + + + + + +

Check the unity build object for unexpected exported symbols.

+
+ + + + + + + + + + + + +

Add a line length linter and fix formatting issues.

@@ -230,6 +435,8 @@ + + @@ -240,7 +447,6 @@ - @@ -265,7 +471,268 @@

Modernize the website. Special thanks to Jan for the insightful (and hilarious) logo.

+ +

The website has a new design with light and dark themes and a layout that works on phones. Pages with a table of contents show it beside the text and mark the section being read. Commands and config files can be copied with a button, config files mark the lines each section changes, and release notes can be expanded to show more detail.

+
+ + + + + + + + + +

Document the release schedule.

+ +

Feature releases are scheduled for the third Monday of January, April, July, and October. Patch releases are scheduled for the third Monday of any other month as required. The release notes introduction also describes the major, minor, and patch parts of a release number.

+
+ + + + + + + + + +

Migrate the documentation tools from C and Perl to Python.

+ +

The documentation is built by doc/doc.py instead of a C tool run by doc/doc.pl, and building the documentation no longer requires Perl.

+ + + + + + + + + + + + +

Generate DIST.md from XML and improve the generated markdown.

+
+ + + + + + + + + + +

Check documentation links and option allow lists.

+
+ + + + + + + + + + + + + +

Improve the documentation build and deploy.

+
+ + + + + + + + + + + + + +

Improve the documentation build containers.

+
+ + + + + + +

Merge coding standards into the contributing guide.

+
+
+ + + + + + + + + + + +

Migrate the test harness from C and Perl to Python.

+ +

Tests are run with test/test.py instead of test/test.pl. The test containers and CI runners no longer require Perl and the harness is covered by tests.

+
+ + + + + + + + + + +

Add a Fil-C job to CI.

+ +

Fil-C is a memory-safe implementation of C that checks every pointer access. It found two out-of-bounds reads that gcc, clang, and Valgrind missed. A new workflow also builds and tests on the CI runner with gcc and clang, with and without the optional libraries.

+
+ + + + + + + + +

Add fuzz testing for the JSON, Ini, and Pack readers.

+ +

The readers are fuzzed with libFuzzer, AddressSanitizer, and UndefinedBehaviorSanitizer in CI. Fuzzing found several bugs in how invalid input is read, e.g. deeply nested JSON arrays in an info file or an object store response could overflow the memory context stack.

+
+ + + + + + + + + + +

Allow test user names that adduser on Debian rejects.

+ +

The test container is built with the same user name as the host user. Debian's adduser rejects names that contain a dot, e.g. first.last, so the container build failed on Debian-based images for these users.

+
+
+ + + + + + + + + + + +

Fix test builds with clang and without optional libraries.

+
+ + + + + + + + + + + + + + + + + + + + + + +

Improve the Python test harness.

+
+ + + + + + + + + + + + +

CI updates.

+
+ + + + + + + + + + + + +

Check that every code and test module is defined and covered.

+
+ + + + + + + + + + + + + + +

Improve unit and integration tests.

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/xml/release/contributor.xml b/doc/xml/release/contributor.xml index d6e0766ea..4714f2ce2 100644 --- a/doc/xml/release/contributor.xml +++ b/doc/xml/release/contributor.xml @@ -60,6 +60,11 @@ arogozin + + Aleksey Tsalolikhin + atsaloli + + Ale&scaron; Zelen&yacute; aleszeleny @@ -675,6 +680,11 @@ j-naylor + + John W. Terrell + john-terrell + + Jordan English jordanenglish @@ -765,6 +775,11 @@ retrodood + + Kian-Meng Ang + kianmeng + + krmozejko krmozejko diff --git a/test/src/module/doc/command/render/release_test.py b/test/src/module/doc/command/render/release_test.py index 1f6ded653..67da1d813 100644 --- a/test/src/module/doc/command/render/release_test.py +++ b/test/src/module/doc/command/render/release_test.py @@ -67,6 +67,7 @@ RELEASE_LIST = """ +

Fix a bug.

@@ -138,12 +139,15 @@ RELEASE_LIST = """ # Releases with details and the history they are checked against DETAIL_HISTORY = [ + ("dB", "Merge v2.10.1 release."), + ("dA", "Fix a bug on a branch."), + ("d8", "Rework the internals."), ("d0", "Improve speed."), ("d1", "Add a feature."), ("d2", "Fix a bug."), ("d3", 'Fix a "quoted" .'), ("d4", "Begin v2.60.0 development."), - ("d5", "v2.59.0: Prior."), + ("d5", "v2.10.0: Prior."), ("d6", "Improve a thing."), ("d7", "v1.00: Initial."), ] @@ -181,10 +185,23 @@ DETAIL_RELEASE_LIST = """

Speed things up.

+ + + +

Rework the internals.

+
+
+ + + + + + + - + @@ -194,7 +211,7 @@ DETAIL_RELEASE_LIST = """ - + @@ -227,18 +244,28 @@ def _doc(release_list=RELEASE_LIST, contributor=CONTRIBUTOR): #################################################################################################################################### -def _render(content=None, dev=False, history=HISTORY): +def _history(history): + """The cached form of a history.""" + + return [{"commit": commit, "date": "2026-07-30 00:00:00 +0000", "subject": subject} for commit, subject in history] + + +#################################################################################################################################### +def _render(content=None, dev=False, history=HISTORY, claim=True, history_tag=None): """Build the release document from a release list.""" with tempfile.TemporaryDirectory() as path: file_write( os.path.join(path, "resource/git-history.cache"), json.dumps( - [{"commit": commit, "date": "2026-07-30 00:00:00 +0000", "subject": subject} for commit, subject in history] + { + "head": _history(history), + "tag": {} if history_tag is None else {version: _history(tag) for version, tag in history_tag.items()}, + } ), ) - return release_render(xml_parse(_doc() if content is None else content, "test.xml"), path, dev) + return release_render(xml_parse(_doc() if content is None else content, "test.xml"), path, dev, claim) #################################################################################################################################### @@ -342,7 +369,7 @@ def test_release_render_item(): item = xml_node_child(xml_node_child(release, "list"), "list-item") # The default contributor is dropped where they are the only one, so their name is not on every line of the page - assert_equal(xml_node_content(item), "Fix a bug. (Reported by Other Person.)") + assert_equal(xml_node_content(item), "Fix a bug. (Tested by Third Person. Reported by Other Person.)") # A release of the documentation says so, and an item written as more than one paragraph reads as one line supported = xml_node_child_list(root, "section")[3] @@ -460,7 +487,7 @@ def test_release_render_contributor(): _render( _doc( RELEASE_LIST.replace( - 'id="other.person"/>\n \n\n' + 'id="third.person"/>\n \n\n' "

Fix a bug.", 'id="nobody"/>\n \n\n' "

Fix a bug.", @@ -530,7 +557,7 @@ def test_release_render_commit_ambiguous(): #################################################################################################################################### def test_release_render_detail(): - """Releases with version >= 2.60 have the paragraphs after the first and the links of an item in details.""" + """Releases with version >= _DETAIL_VERSION_MIN have the paragraphs after the first and the links of an item in details.""" root = _render(_doc(DETAIL_RELEASE_LIST), history=DETAIL_HISTORY) @@ -573,7 +600,7 @@ def test_release_render_detail(): ], ) - # Releases with version < 2.60 have no details + # Releases with version < _DETAIL_VERSION_MIN have no details supported = xml_node_child_list(root, "section")[2] assert_equal(_item_html(xml_node_child_list(supported, "section")[1]), ["Improve a thing. Say more."]) @@ -640,26 +667,530 @@ def test_release_render_detail_dev(): ) +#################################################################################################################################### +def test_release_render_commit_id(): + """A commit can be named by id when more than one commit has the same subject.""" + + history = DETAIL_HISTORY[:3] + [("e1", "Fix lines."), ("e2", "Fix lines.")] + DETAIL_HISTORY[3:] + release_list = DETAIL_RELEASE_LIST.replace( + "", + """ + + + +

Fix lines.

+
+ """, + 1, + ) + + root = _render(_doc(release_list), history=history) + release = xml_node_child_list(xml_node_child_list(root, "section")[1], "section")[0] + + assert_equal( + _item_html(release)[3], + "Fix lines." + + DETAIL_HTML + + '\n
' + + 'e1' + + " Fix lines.
" + + '\n
' + + 'e2' + + " Fix lines.
", + ) + + # An id that is not in the release + with assert_raises(ToolError) as raised: + _render(_doc(release_list.replace('', '')), history=history) + + assert_equal(str(raised.exception), "unable to find attribute 'subject' in node 'commit'") + + with assert_raises(ToolError) as raised: + _render( + _doc(release_list.replace('', '')), + history=history, + ) + + assert_equal(str(raised.exception), "release 2.60.0 commit id 'e2' subject 'Fix lines.' does not begin with 'Fix more lines.'") + + +#################################################################################################################################### +def test_release_render_backpatch(): + """Commits back-patched to a patch release are listed on a development build, grouped by the version of the patch release.""" + + root = _render(_doc(DETAIL_RELEASE_LIST), dev=True, history=DETAIL_HISTORY) + release = xml_node_child_list(xml_node_child_list(root, "section")[1], "section")[0] + + assert_in("Back-Patched:", "".join(xml_node_content(node) for node in xml_node_child_list(release, "p"))) + assert_equal( + _item_html(release)[-1], + 'Back-patched to v2.10.1.' + + DETAIL_HTML + + '\n
' + + 'dA' + + " Fix a bug on a branch.
" + + '\n
' + + 'dB' + + " Merge v2.10.1 release.
", + ) + + # The commits are claimed but not listed on a release build + root = _render(_doc(DETAIL_RELEASE_LIST), history=DETAIL_HISTORY) + + assert_not_in("Back-Patched:", xml_node_content(xml_node_child_list(xml_node_child_list(root, "section")[1], "section")[0])) + + # The version must be a patch release in the list + for backpatch_version in ("2.10.0", "2.09.1"): + with assert_raises(ToolError) as raised: + _render( + _doc( + DETAIL_RELEASE_LIST.replace( + '', '' % backpatch_version + ) + ), + history=DETAIL_HISTORY, + ) + + assert_equal(str(raised.exception), "release 2.60.0 back-patch version %s is not a patch release" % backpatch_version) + + # A back-patch has commits + with assert_raises(ToolError) as raised: + _render( + _doc( + DETAIL_RELEASE_LIST.replace( + '', + '\n ', + ) + ), + history=DETAIL_HISTORY, + ) + + assert_equal(str(raised.exception), "release 2.60.0 back-patch version 2.10.1 has no commits") + + +# Development items that name the release note of a later release +NOTE_RELEASE_LIST = """ + + + + +

Finish the thing.

+
+
+
+
+ + + + + +

Add the thing.

+
+
+ + + +

Add the thing to the docs.

+
+
+ + + + + +

Polish the thing.

+
+
+
+
+ + + + + +

Improve a thing.

+
+
+ + + + + + + +

Prepare for the thing.

+
+ + + + + +

Start the thing.

+
+ + + + +

Tidy the thing.

+
+
+
+
+ + +""" + +NOTE_HISTORY = [ + ("p3", "v2.62.0: Final."), + ("p1", "Finish the thing."), + ("n4", "v2.61.0: Beta."), + ("n3", "Add the thing to the docs."), + ("n2", "Polish the thing."), + ("n1", "Add the thing."), + ("m5", "v2.60.0: Start."), + ("m6", "Tidy the thing."), + ("m4", "Refactor for the thing."), + ("m3", "Prepare the thing."), + ("m2", "Start the thing."), + ("m1", "Improve a thing."), + ("m0", "v1.00: Initial."), +] + + +#################################################################################################################################### +def test_release_render_release_note(): + """A development item may name the release note of a later release, which lists the development item in its details.""" + + root = _render(_doc(NOTE_RELEASE_LIST), history=NOTE_HISTORY) + current = xml_node_child_list(xml_node_child_list(root, "section")[1], "section")[0] + supported = xml_node_child_list(xml_node_child_list(root, "section")[2], "section") + + assert_equal( + _item_html(current), + [ + "Finish the thing." + + DETAIL_HTML + + '\n
Commit ' + + 'p1
' + + '\n
' + + 'Development in v2.61.0:
' + + '\n
' + + 'n2' + + " Polish the thing.
" + ], + ) + + # Development items of the same release are listed under one line and the links of a development item with one commit are on the + # line of the commit + assert_equal( + _item_html(supported[0])[0], + "Add the thing." + + DETAIL_HTML + + '\n
Commit ' + + 'n1
' + + '\n
' + + 'Development in v2.60.0:
' + + '\n
' + + 'm3' + + " Prepare the thing.
" + + '\n
' + + 'm4' + + " Refactor for the thing.
" + + '\n
' + + 'm2' + + " Start the thing." + + 'Pull request #8
' + + '\n
' + + 'm6' + + " Tidy the thing.
", + ) + + # A development build links a development item to the release of its release note + root = _render(_doc(NOTE_RELEASE_LIST), dev=True, history=NOTE_HISTORY) + supported = xml_node_child_list(xml_node_child_list(root, "section")[2], "section") + + assert_equal( + _item_html(supported[1])[1], + "Prepare for the thing." + + DETAIL_HTML + + '\n
' + + 'Development for Add the thing in v2.61.0:
' + + '\n
' + + 'm3' + + " Prepare the thing.
" + + '\n
' + + 'm4' + + " Refactor for the thing.
", + ) + + assert_equal( + _item_html(supported[1])[2], + "Start the thing." + + DETAIL_HTML + + '\n
' + + 'Development for Add the thing in v2.61.0:
' + + '\n
' + + 'Pull request #8' + + 'Commit ' + + 'm2
', + ) + + # A release in development is named by the version it will have when it is released + root = _render( + _doc(NOTE_RELEASE_LIST.replace('date="2026-12-01" version="2.62.0"', 'date="XXXX-XX-XX" version="2.62.0dev"')), + dev=True, + history=NOTE_HISTORY[1:], + ) + current = xml_node_child_list(xml_node_child_list(root, "section")[2], "section")[0] + + assert_equal( + _item_html(current)[2], + "Polish the thing." + + DETAIL_HTML + + '\n
' + + 'Development for Finish the thing in ' + + 'v2.62.0dev:
' + + '\n
Commit ' + + 'n2
', + ) + + # The release note must be in a later release + for version in ("2.60.0", "2.70.0"): + with assert_raises(ToolError) as raised: + _render( + _doc( + NOTE_RELEASE_LIST.replace( + 'version="2.61.0" subject="Add the thing."', 'version="%s" subject="Add"' % version, 1 + ) + ), + history=NOTE_HISTORY, + ) + + assert_equal(str(raised.exception), "release 2.60.0 release note version %s is not a later release" % version) + + # The release note must be found once + with assert_raises(ToolError) as raised: + _render( + _doc(NOTE_RELEASE_LIST.replace('subject="Add the thing."', 'subject="Add another thing."', 1)), history=NOTE_HISTORY + ) + + assert_equal(str(raised.exception), "release 2.60.0 release note 'Add another thing.' not found in release 2.61.0") + + with assert_raises(ToolError) as raised: + _render(_doc(NOTE_RELEASE_LIST.replace('subject="Add the thing."', 'subject="Add the thing"', 1)), history=NOTE_HISTORY) + + assert_equal(str(raised.exception), "release 2.60.0 release note 'Add the thing' found more than once in release 2.61.0") + + # Only a development item may name a release note + with assert_raises(ToolError) as raised: + _render( + _doc( + NOTE_RELEASE_LIST.replace( + "

Finish the thing.

", '\n

Finish the thing.

' + ) + ), + history=NOTE_HISTORY, + ) + + assert_equal( + str(raised.exception), "release 2.62.0 item 'Finish the thing.' is not a development item and cannot name a release note" + ) + + +# A patch release built on a branch of its own +PATCH_RELEASE_LIST = """ + + + + +

Improve more.

+
+
+
+
+ + + + + +

Fix a bug on a branch.

+ +

Say more.

+
+
+ + + +

Fix the build on a branch.

+
+
+
+
+ + + + + +

Improve a thing.

+
+
+
+
+ + +""" + +PATCH_HISTORY = [ + ("n2", "v2.61.0: Next."), + ("n1", "Improve more."), + ("n0", "Begin v2.61.0 development."), + ("m2", "v2.60.0: Detail."), + ("m1", "Improve a thing."), + ("m0", "v1.00: Initial."), +] + +PATCH_HISTORY_TAG = { + "2.60.1": [ + ("t3", "v2.60.1: Patch."), + ("t2", "Fix the build on a branch."), + ("t1", "Fix a bug on a branch."), + ("t0", "Begin v2.60.1 development."), + ] +} + + +#################################################################################################################################### +def test_release_render_patch(): + """A patch release that is not the most recent is checked against the history of its tag.""" + + root = _render(_doc(PATCH_RELEASE_LIST), dev=True, history=PATCH_HISTORY, history_tag=PATCH_HISTORY_TAG) + release = xml_node_child_list(xml_node_child_list(root, "section")[2], "section")[0] + + assert_equal(xml_node_attribute(release, "id"), "2.60.1") + assert_equal( + _item_html(release), + [ + "Fix a bug on a branch." + + DETAIL_HTML + + '\n
Say more.
' + + '\n
Commit ' + + 't1
', + "Fix the build on a branch." + + DETAIL_HTML + + '\n
Commit ' + + 't2
', + ], + ) + + # Every commit of the patch release is claimed by an item + with assert_raises(ToolError) as raised: + _render( + _doc(PATCH_RELEASE_LIST.replace("

Fix the build on a branch.

", "

Fix the build elsewhere.

")), + history=PATCH_HISTORY, + history_tag=PATCH_HISTORY_TAG, + ) + + assert_in("unable to find commit or no subject match for release 2.60.1 item 'Fix the build elsewhere.'", str(raised.exception)) + + with assert_raises(ToolError) as raised: + _render( + _doc(PATCH_RELEASE_LIST), + history=PATCH_HISTORY, + history_tag={"2.60.1": [("t4", "Do something unclaimed.")] + PATCH_HISTORY_TAG["2.60.1"]}, + ) + + assert_in("release 2.60.1 has commits that no item claims:\n2026-07-30 t4: Do something unclaimed.", str(raised.exception)) + + # A patch release after another patch release ends at the commit that closed the one before it + release_before = """ + + + +

Fix an earlier bug.

+
+
+
+
+ + """ + release_list = PATCH_RELEASE_LIST.replace('version="2.60.1" title="Patch"', 'version="2.60.2" title="Patch"').replace( + 'Fix the build on a branch.

", "

Fix the build elsewhere.

")), + history=PATCH_HISTORY, + ) + + #################################################################################################################################### def test_release_render_bug_fix(): """A bug fix release x.y.z with z > 0 is skipped when it is not the most recent and a release x.y.0 is checked.""" - # The commits of 2.60.0 end at the commit that closed 2.59.0 + # The commits of 2.60.0 end at the commit that closed 2.10.0 with assert_raises(ToolError) as raised: _render(_doc(DETAIL_RELEASE_LIST.replace("

Add a feature.

", "

Improve a thing.

")), history=DETAIL_HISTORY) assert_in("unable to find commit or no subject match for release 2.60.0 item 'Improve a thing.'", str(raised.exception)) - # 2.59.0 is checked + # Development on 2.60.0 may have been opened as 2.60 + _render( + _doc(DETAIL_RELEASE_LIST), + history=[("d4", "Begin v2.60 development.") if commit == "d4" else (commit, subject) for commit, subject in DETAIL_HISTORY], + ) + + # Every commit of 2.60.0 is claimed by an item + with assert_raises(ToolError) as raised: + _render(_doc(DETAIL_RELEASE_LIST), history=[("d9", "Do something unclaimed.")] + DETAIL_HISTORY) + + assert_in("release 2.60.0 has commits that no item claims:\n2026-07-30 d9: Do something unclaimed.", str(raised.exception)) + + # Commits that no item claims are allowed when claim is false + _render(_doc(DETAIL_RELEASE_LIST), history=[("d9", "Do something unclaimed.")] + DETAIL_HISTORY, claim=False) + + # 2.10.0 is checked with assert_raises(ToolError) as raised: _render(_doc(DETAIL_RELEASE_LIST.replace("

Improve a thing.

", "

Improve two things.

")), history=DETAIL_HISTORY) - assert_in("unable to find commit or no subject match for release 2.59.0 item 'Improve two things.'", str(raised.exception)) + assert_in("unable to find commit or no subject match for release 2.10.0 item 'Improve two things.'", str(raised.exception)) #################################################################################################################################### def test_release_history_update(): - """The history is written from git when HEAD is not the newest commit in it.""" + """The history is written from git when the newest commit in it or in the tag of a patch release has changed.""" with tempfile.TemporaryDirectory() as path: path_doc = os.path.join(path, "doc") @@ -669,25 +1200,34 @@ def test_release_history_update(): _commit(path, "Add a feature.", "What the feature does.") _commit(path, "v2.01: First.", "The release notes.") - release_history_update(path, path_doc) + # With no integration branch the history ends at HEAD + assert_false(release_history_update(path, path_doc)) history = json.loads(file_read(path_history)) - assert_equal(history[0]["commit"], exec_one("git -C %s rev-parse HEAD" % path).strip()) - assert_equal(sorted(history[1]), ["body", "commit", "date", "subject"]) + assert_equal(history["head"][0]["commit"], exec_one("git -C %s rev-parse HEAD" % path).strip()) + assert_equal(sorted(history["head"][1]), ["body", "commit", "date", "subject"]) + assert_equal(history["tag"], {}) # The body of a commit that closed a release is left out assert_equal( - [(commit["subject"], commit.get("body")) for commit in history], + [(commit["subject"], commit.get("body")) for commit in history["head"]], [("v2.01: First.", None), ("Add a feature.", "What the feature does.")], ) # The history is not written while HEAD is the newest commit in it - file_write(path_history, json.dumps(history[:1])) + file_write(path_history, json.dumps({"head": history["head"][:1], "tag": {}})) release_history_update(path, path_doc) - assert_equal(len(json.loads(file_read(path_history))), 1) + assert_equal(len(json.loads(file_read(path_history))["head"]), 1) + + # A history written in the format before patch releases were read from their tags is written again + file_write(path_history, json.dumps(history["head"][:1])) + + release_history_update(path, path_doc) + + assert_equal(len(json.loads(file_read(path_history))["head"]), 2) # A new commit is first in the history _commit(path, "Fix a bug.") @@ -695,5 +1235,54 @@ def test_release_history_update(): release_history_update(path, path_doc) assert_equal( - [commit["subject"] for commit in json.loads(file_read(path_history))], ["Fix a bug.", "v2.01: First.", "Add a feature."] + [commit["subject"] for commit in json.loads(file_read(path_history))["head"]], + ["Fix a bug.", "v2.01: First.", "Add a feature."], ) + + # The history of a patch release with version >= _DETAIL_VERSION_MIN is the commits of its tag that are not in the history + # of HEAD. Other release tags are left out. + branch = exec_one("git -C %s branch --show-current" % path).strip() + + exec_one("git -C %s tag release/2.60.0" % path) + exec_one("git -C %s tag release/2.10.1" % path) + exec_one("git -C %s checkout -q -b patch" % path) + _commit(path, "Fix a bug on a branch.") + exec_one("git -C %s tag release/2.60.1" % path) + exec_one("git -C %s checkout -q %s" % (path, branch)) + + release_history_update(path, path_doc) + + history = json.loads(file_read(path_history)) + + assert_equal(list(history["tag"]), ["2.60.1"]) + assert_equal([commit["subject"] for commit in history["tag"]["2.60.1"]], ["Fix a bug on a branch."]) + + # The history is written again when the tag of a patch release moves + exec_one("git -C %s checkout -q patch" % path) + _commit(path, "v2.60.1: Patch.") + exec_one("git -C %s tag -f release/2.60.1" % path) + exec_one("git -C %s checkout -q %s" % (path, branch)) + + release_history_update(path, path_doc) + + assert_equal( + [commit["subject"] for commit in json.loads(file_read(path_history))["tag"]["2.60.1"]], + ["v2.60.1: Patch.", "Fix a bug on a branch."], + ) + + # With an integration branch related to HEAD the history ends at the newest commit of HEAD that is also in integration + exec_one("git -C %s branch integration" % path) + _commit(path, "RELEASE: Add release notes.") + + assert_true(release_history_update(path, path_doc)) + assert_equal(json.loads(file_read(path_history))["head"][0]["subject"], "Fix a bug.") + + # With an integration branch that is not related to HEAD the history ends at HEAD + tree = exec_one("git -C %s hash-object -t tree /dev/null" % path).strip() + commit = exec_one( + "git -C %s -c user.name=test -c user.email=test@pgbackrest.org commit-tree %s -m 'Unrelated.'" % (path, tree) + ).strip() + exec_one("git -C %s update-ref refs/heads/integration %s" % (path, commit)) + + assert_false(release_history_update(path, path_doc)) + assert_equal(json.loads(file_read(path_history))["head"][0]["subject"], "RELEASE: Add release notes.")