Browse Source

Update release instructions for documentation. (#7846)

* Add linkpatch tool to rewrite documentation URLs.
* Update instructions for creating backport branches.

Updates #7675.
pull/7909/head
M. J. Fromberger 2 years ago
committed by GitHub
parent
commit
bd6fce13ae
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 237 additions and 2 deletions
  1. +28
    -1
      RELEASES.md
  2. +1
    -1
      docs/README.md
  3. +1
    -0
      go.mod
  4. +2
    -0
      go.sum
  5. +205
    -0
      scripts/linkpatch/linkpatch.go

+ 28
- 1
RELEASES.md View File

@ -42,15 +42,42 @@ In the following example, we'll assume that we're making a backport branch for
the 0.35.x line.
1. Start on `master`
2. Create and push the backport branch:
```sh
git checkout -b v0.35.x
git push origin v0.35.x
```
3. Create a PR to update the documentation directory for the backport branch.
We only maintain RFC and ADR documents on master, to avoid confusion.
In addition, we rewrite Markdown URLs pointing to master to point to the
backport branch, so that generated documentation will link to the correct
versions of files elsewhere in the repository. For context on the latter,
see https://github.com/tendermint/tendermint/issues/7675.
To prepare the PR:
```sh
# Remove the RFC and ADR documents from the backport.
# We only maintain these on master to avoid confusion.
git rm -r docs/rfc docs/architecture
# Update absolute links to point to the backport.
go run ./scripts/linkpatch -recur -target v0.35.x -skip-path docs/DOCS_README.md,docs/README.md docs
# Create and push the PR.
git checkout -b update-docs-v035x
git commit -m "Update docs for v0.35.x backport branch." docs
git push -u origin update-docs-v035x
```
Be sure to merge this PR before making other changes on the newly-created
backport branch.
After doing these steps, go back to `master` and do the following:
1. Tag `master` as the dev branch for the _next_ major release and push it back up.
1. Tag `master` as the dev branch for the _next_ major release and push it up to GitHub.
For example:
```sh
git tag -a v0.36.0-dev -m "Development base for Tendermint v0.36."


+ 1
- 1
docs/README.md View File

@ -21,7 +21,7 @@ Tendermint?](introduction/what-is-tendermint.md).
To get started quickly with an example application, see the [quick start guide](introduction/quick-start.md).
To learn about application development on Tendermint, see the [Application Blockchain Interface](https://github.com/tendermint/tendermint/tree/master/spec/abci).
To learn about application development on Tendermint, see the [Application Blockchain Interface](../spec/abci).
For more details on using Tendermint, see the respective documentation for
[Tendermint Core](tendermint-core/), [benchmarking and monitoring](tools/), and [network deployments](nodes/).


+ 1
- 0
go.mod View File

@ -67,6 +67,7 @@ require (
github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af // indirect
github.com/containerd/continuity v0.2.1 // indirect
github.com/daixiang0/gci v0.3.1-0.20220208004058-76d765e3ab48 // indirect
github.com/creachadair/atomicfile v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denis-tingajkin/go-header v0.4.2 // indirect
github.com/dgraph-io/badger/v2 v2.2007.2 // indirect


+ 2
- 0
go.sum View File

@ -217,6 +217,8 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creachadair/atomicfile v0.2.4 h1:GRjpQLmz/78I4+nBQpGMFrRa9yrL157AUTrA6hnF0YU=
github.com/creachadair/atomicfile v0.2.4/go.mod h1:BRq8Une6ckFneYXZQ+kO7p1ZZP3I2fzVzf28JxrIkBc=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=


+ 205
- 0
scripts/linkpatch/linkpatch.go View File

@ -0,0 +1,205 @@
// Program linkpatch rewrites absolute URLs pointing to targets in GitHub in
// Markdown link tags to target a different branch.
//
// This is used to update documentation links for backport branches.
// See https://github.com/tendermint/tendermint/issues/7675 for context.
package main
import (
"bytes"
"flag"
"fmt"
"io/fs"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/creachadair/atomicfile"
)
var (
repoName = flag.String("repo", "tendermint/tendermint", "Repository name to match")
sourceBranch = flag.String("source", "master", "Source branch name (required)")
targetBranch = flag.String("target", "", "Target branch name (required)")
doRecur = flag.Bool("recur", false, "Recur into subdirectories")
skipPath stringList
skipMatch regexpFlag
// Match markdown links pointing to absolute URLs.
// This only works for "inline" links, not referenced links.
// The submetch selects the URL.
linkRE = regexp.MustCompile(`(?m)\[.*?\]\((https?://.*?)\)`)
)
func init() {
flag.Var(&skipPath, "skip-path", "Skip these paths (comma-separated)")
flag.Var(&skipMatch, "skip-match", "Skip URLs matching this regexp (RE2)")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, `Usage: %[1]s [options] <file/dir>...
Rewrite absolute Markdown links targeting the specified GitHub repository
and source branch name to point to the target branch instead. Matching
files are updated in-place.
Each path names either a directory to list, or a single file path to
rewrite. By default, only the top level of a directory is scanned; use -recur
to recur into subdirectories.
Options:
`, filepath.Base(os.Args[0]))
flag.PrintDefaults()
}
}
func main() {
flag.Parse()
switch {
case *repoName == "":
log.Fatal("You must specify a non-empty -repo name (org/repo)")
case *targetBranch == "":
log.Fatal("You must specify a non-empty -target branch")
case *sourceBranch == "":
log.Fatal("You must specify a non-empty -source branch")
case *sourceBranch == *targetBranch:
log.Fatalf("Source and target branch are the same (%q)", *sourceBranch)
case flag.NArg() == 0:
log.Fatal("You must specify at least one file/directory to rewrite")
}
r, err := regexp.Compile(fmt.Sprintf(`^https?://github.com/%s/(?:blob|tree)/%s`,
*repoName, *sourceBranch))
if err != nil {
log.Fatalf("Compiling regexp: %v", err)
}
for _, path := range flag.Args() {
if err := processPath(r, path); err != nil {
log.Fatalf("Processing %q failed: %v", path, err)
}
}
}
func processPath(r *regexp.Regexp, path string) error {
fi, err := os.Lstat(path)
if err != nil {
return err
}
if fi.Mode().IsDir() {
return processDir(r, path)
} else if fi.Mode().IsRegular() {
return processFile(r, path)
}
return nil // nothing to do with links, device files, sockets, etc.
}
func processDir(r *regexp.Regexp, root string) error {
return filepath.Walk(root, func(path string, fi fs.FileInfo, err error) error {
if err != nil {
return err
}
if fi.IsDir() {
if skipPath.Contains(path) {
log.Printf("Skipping %q (per -skip-path)", path)
return filepath.SkipDir // explicitly skipped
} else if !*doRecur && path != root {
return filepath.SkipDir // skipped because we aren't recurring
}
return nil // nothing else to do for directories
} else if skipPath.Contains(path) {
log.Printf("Skipping %q (per -skip-path)", path)
return nil // explicitly skipped
} else if filepath.Ext(path) != ".md" {
return nil // nothing to do for non-Markdown files
}
return processFile(r, path)
})
}
func processFile(r *regexp.Regexp, path string) error {
log.Printf("Processing file %q", path)
input, err := os.ReadFile(path)
if err != nil {
return err
}
pos := 0
var output bytes.Buffer
for _, m := range linkRE.FindAllSubmatchIndex(input, -1) {
href := string(input[m[2]:m[3]])
u := r.FindStringIndex(href)
if u == nil || skipMatch.MatchString(href) {
if u != nil {
log.Printf("Skipped URL %q (by -skip-match)", href)
}
output.Write(input[pos:m[1]]) // copy the existing data as-is
pos = m[1]
continue
}
// Copy everything before the URL as-is, then write the replacement.
output.Write(input[pos:m[2]]) // everything up to the URL
fmt.Fprintf(&output, `https://github.com/%s/blob/%s%s`, *repoName, *targetBranch, href[u[1]:])
// Write out the tail of the match, everything after the URL.
output.Write(input[m[3]:m[1]])
pos = m[1]
}
output.Write(input[pos:]) // the rest of the file
_, err = atomicfile.WriteAll(path, &output, 0644)
return err
}
// stringList implements the flag.Value interface for a comma-separated list of strings.
type stringList []string
func (lst *stringList) Set(s string) error {
if s == "" {
*lst = nil
} else {
*lst = strings.Split(s, ",")
}
return nil
}
// Contains reports whether lst contains s.
func (lst stringList) Contains(s string) bool {
for _, elt := range lst {
if s == elt {
return true
}
}
return false
}
func (lst stringList) String() string { return strings.Join([]string(lst), ",") }
// regexpFlag implements the flag.Value interface for a regular expression.
type regexpFlag struct{ *regexp.Regexp }
func (r regexpFlag) MatchString(s string) bool {
if r.Regexp == nil {
return false
}
return r.Regexp.MatchString(s)
}
func (r *regexpFlag) Set(s string) error {
c, err := regexp.Compile(s)
if err != nil {
return err
}
r.Regexp = c
return nil
}
func (r regexpFlag) String() string {
if r.Regexp == nil {
return ""
}
return r.Regexp.String()
}

Loading…
Cancel
Save