mirror of https://github.com/apache/druid.git
add utility to aid in formatting release notes to be linkable (#11728)
* add utility to aid in formatting release notes to be linkable * add docs
This commit is contained in:
parent
621e5ac63f
commit
2593df5e5b
|
@ -193,6 +193,7 @@ These additional tools were largely used to bootstrap the initial `LICENSE`, `LI
|
|||
| [jar-notice-lister](bin/jar-notice-lister.py) | Point this to an extracted Druid binary distribution, and give it a temp scratch directory, and it will output NOTICE information for all the Druid JAR files. |
|
||||
|
||||
|
||||
|
||||
The `licenses.yaml` dependency registry serves to help ease the process of managing releases and maintaining `LICENSE` and `NOTICE` compliance for a project as complex and with as many dependencies as Druid.
|
||||
|
||||
## Release notes
|
||||
|
@ -205,10 +206,13 @@ It is also the release managers responsibility for correctly assigning all PRs m
|
|||
| [get-milestone-prs](bin/get-milestone-prs.py) | lists PRs between tags or commits and the milestone associated with them. |
|
||||
| [tag-missing-milestones](bin/tag-missing-milestones.py) | Find pull requests which the milestone is missing and tag them properly. |
|
||||
| [find-missing-backports](bin/find-missing-backports.py) | Find PRs which have been back-ported to one release branch but not another. Useful if a bug fix release based on the previous release is required during a release cycle. |
|
||||
| [make-linkable-release-notes](bin/make-linkable-release-notes.py) | given input of a version, input markdown file path, and output markdown file path, will rewrite markdown headers of the input file to have embedded links in the release notes style. |
|
||||
|
||||
|
||||
Next create an issue in the Druid github to contain the release notes and allow the community to provide feedback prior to the release. Make sure to attach it to the release milestone in github. It is highly recommended to review [previous release notes for reference](https://github.com/apache/druid/releases) of how to best structure them. Be sure to call out any exciting new features, important bug fixes, and any compatibility concerns for users or operators to consider when upgrading to this release.
|
||||
|
||||
The [make-linkable-release-notes](bin/make-linkable-release-notes.py) script can assist in converting plain markdown into a version with headers that have embedded self links, to allow directly linking to specific release note entries.
|
||||
|
||||
## Web console package version
|
||||
Make sure the web console Javascript package version matches the upcoming release version prior to making tags and artifacts. You can find the release version in [package.json](../web-console/package.json). This should be set correctly, but if it isn't, it can be set with:
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import urllib.parse
|
||||
|
||||
def get_header_level(line):
|
||||
count = 0
|
||||
for element in line:
|
||||
if element == '#':
|
||||
count = count + 1
|
||||
else:
|
||||
break
|
||||
return count
|
||||
|
||||
def make_link_text(prefix, text):
|
||||
return "{}-{}".format(prefix, urllib.parse.quote_plus(text.lower().replace(' ', '-')))
|
||||
|
||||
def process_release_notes(release_version, release_notes, outfile):
|
||||
"""
|
||||
rewrites markdown headers with an embedded html link so that github release notes can become linkable.
|
||||
|
||||
parent header text is url-encoded and prefixed to the link text so that links are ensured to be unique, albeit a
|
||||
bit long.
|
||||
|
||||
e.g.
|
||||
# New features
|
||||
...
|
||||
## Queries
|
||||
...
|
||||
### Some cool feature
|
||||
|
||||
becomes:
|
||||
# <a name="0.22.0-new-features" href="#0.22.0.new-features">#</a> New features
|
||||
...
|
||||
## <a name="0.22.0-new-features-queries" href="...">#</a> Queries
|
||||
...
|
||||
### <a name="0.22.0-new-features-queries-some-cool-feature" href="...">#</a> Some cool feature
|
||||
|
||||
Markdown headers which already have an embedded link of this form will be ignored (though this logic isn't very
|
||||
smart, if it starts with "<a href=" or like, any other valid link form it will be missed...)
|
||||
|
||||
:param release_version: release version is always the first part of the embedded link prefix
|
||||
:param release_notes: markdown file that contains release notes
|
||||
:param outfile: destination for rewritten markdown file
|
||||
:return: nothing
|
||||
"""
|
||||
with open(args.out_path, "w", encoding="utf-8") as outfile:
|
||||
with open(release_notes, encoding="utf-8") as file:
|
||||
current_level = 0
|
||||
current_prefix = release_version
|
||||
levels = []
|
||||
prefixes = []
|
||||
for line in file:
|
||||
header_level = get_header_level(line)
|
||||
header_text = line[header_level + 1:len(line) - 1]
|
||||
if (header_level > 0 and "<a name=" not in line):
|
||||
if header_level > current_level:
|
||||
levels.append(current_level)
|
||||
prefixes.append(current_prefix)
|
||||
current_level = header_level
|
||||
elif header_level < current_level:
|
||||
current_level = levels.pop()
|
||||
prefixes.pop()
|
||||
while (header_level < current_level):
|
||||
current_level = levels.pop()
|
||||
prefixes.pop()
|
||||
|
||||
current_prefix = prefixes.pop()
|
||||
link_text = make_link_text(current_prefix, header_text)
|
||||
prefixes.append(current_prefix)
|
||||
current_prefix = link_text
|
||||
|
||||
print(
|
||||
"{} <a name=\"{}\" href=\"#{}\">#</a> {}".format(
|
||||
line[0:header_level],
|
||||
link_text,
|
||||
link_text,
|
||||
line[header_level + 1:]
|
||||
),
|
||||
file=outfile,
|
||||
end = ''
|
||||
)
|
||||
else:
|
||||
print(line, file=outfile, end = '')
|
||||
return
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
parser = argparse.ArgumentParser(description='rewrite markdown so that headings contain direct links')
|
||||
parser.add_argument('version', metavar='release version', type=str)
|
||||
parser.add_argument('release_notes', metavar='<path to release notes markdown file>', type=str)
|
||||
parser.add_argument('out_path', metavar='<path to output file>', type=str)
|
||||
args = parser.parse_args()
|
||||
|
||||
process_release_notes(args.version, args.release_notes, args.out_path)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print('Interrupted, closing.')
|
Loading…
Reference in New Issue