github.com/whyrusleeping/gx@v0.14.3/contrib/gx-changelog.sh (about)

     1  #!/bin/zsh
     2  
     3  [[ -n "$REPO_FILTER" ]] || REPO_FILTER="github.com/(ipfs|libp2p|ipld)"
     4  [[ -n "$IGNORED_FILES" ]] || IGNORED_FILES='^\(\.gx\|package.json\|\.travis.yml\)$'
     5  
     6  export GOPATH="$(go env GOPATH)"
     7  
     8  alias jq="jq --unbuffered"
     9  
    10  set -e
    11  set -o pipefail
    12  
    13  # Returns a json object recursively listing all deps of the current package.
    14  gx_deps() {
    15      gx deps -r | column  -J --table-columns name,hash,version | jq '.table'
    16  }
    17  
    18  # Convert a stream into an array.
    19  slurp() {
    20      jq -s .
    21  }
    22  
    23  # Convert an array into a stream.
    24  stream() {
    25      jq '.[]'
    26  }
    27  
    28  # Returns a stream of deps changed between $1 and $2.
    29  dep_changes() {
    30      {
    31          <"$1"
    32          <"$2"
    33      } | jq -s 'JOIN(INDEX(.[0][]; .repo); .[1][]; .repo; {repo: .[0].repo, old: .[1].hash, new: .[0].hash}) | select(.new != .old)'
    34  }
    35  
    36  # Replace all gx package names with go import paths.
    37  resolve_repos() {
    38      jq -r '"\(env.GOPATH)/src/gx/ipfs/\(.hash)/\(.name)/package.json \(@json)"' |
    39          while read gxfile json; do
    40              jq --argjson pkg "$json" '($pkg|del(.name)) + {repo: .gx.dvcsimport}' "$gxfile"
    41          done
    42  }
    43  
    44  # Takes in a stream of objects in the form:
    45  # `{ repo: path, old: GxHash, new: GxHash }`
    46  # And returns a stream of objects in the form:
    47  # `{ repo: phat, old: CommitHash, new: CommitHash }`
    48  resolve_commits() {
    49      local repo new old
    50      jq -r '"\(.repo) \(.new) \(.old)"' | while read repo new old; do
    51          local old_commit="null"
    52          local new_commit="null"
    53          local dir="$GOPATH/src/$repo"
    54          while read commit; do
    55              hash="$(git -C "$dir" show "$commit:.gx/lastpubver" 2>/dev/null | cut -d' ' -f2)"
    56              case "$hash" in
    57                  "$new") new_commit="$(printf '"%q"' "$commit")" ;;
    58                  "$old") old_commit="$(printf '"%q"' "$commit")" ;;
    59              esac
    60          done < <(git -C "$dir" log origin/master --format=tformat:'%H' .gx/lastpubver)
    61          printf '{"repo": "%q", "old": %s, "new": %s}\n' "$repo" "$old_commit" "$new_commit"
    62      done | jq
    63  }
    64  
    65  # Generate a release log for a range of commits in a single repo.
    66  release_log() {
    67      local repo="$1"
    68      local start="$2"
    69      local end="${3:-HEAD}"
    70      local ghname="${repo##github.com/}"
    71      local dir="$GOPATH/src/$repo"
    72      
    73          local commit prnum
    74          git -C "$dir" log \
    75              --format='tformat:%H %s' \
    76              --merges \
    77              "$start..$end"  |
    78              sed -n -e 's/\([a-f0-9]\+\) Merge pull request #\([0-9]\+\) from .*/\1 \2/p' |
    79              while read commit prnum; do
    80                  # Skip gx-only PRs.
    81                  git -C "$dir" diff-tree --no-commit-id --name-only "$commit^" "$commit" |
    82                          grep -v "${IGNORED_FILES}" >/dev/null || continue
    83  
    84                  local desc="$(git -C "$dir" show --summary --format='tformat:%b' "$commit" | head -1)"
    85                  printf "- %s ([%s#%s](https://%s/pull/%s))\n" "$desc" "$ghname" "$prnum" "$repo" "$prnum"
    86              done
    87  }
    88  
    89  indent() {
    90      sed -e 's/^/  /'
    91  }
    92  
    93  recursive_release_log() {
    94      local start="${1:-$(git tag -l | sort -V | grep -v -- '-rc' | grep 'v'| tail -n1)}"
    95      local end="${2:-$(git rev-parse HEAD)}"
    96      local repo_root="$(git rev-parse --show-toplevel)"
    97      local package="$(go list)"
    98      (
    99          local workspace="$(mktemp -d)"
   100          trap "$(printf 'rm -rf "%q"' "$workspace")" INT TERM EXIT
   101          cd "$workspace"
   102  
   103          echo "Computing old deps..." >&2
   104          git -C "$repo_root" show "$start:package.json" > "package.json"
   105          gx install --nofancy >/dev/null
   106          gx_deps | stream | resolve_repos | slurp > old_deps.json
   107  
   108          echo "Computing new deps..." >&2
   109          git -C "$repo_root" show "$end:package.json" > "package.json"
   110          gx install --nofancy >/dev/null
   111          gx_deps | stream | resolve_repos | slurp > new_deps.json
   112  
   113          rm package.json
   114  
   115          echo "Generating Changelog..." >&2
   116  
   117          printf "- %s:\n" "$package"
   118          release_log "$package" "$start" "$end" | indent
   119  
   120          dep_changes old_deps.json new_deps.json |
   121              # Filter by repo
   122              jq --arg filter "$REPO_FILTER" 'select(.repo | match($filter))' |
   123              # Add in commit ranges.
   124              resolve_commits |
   125              # Compute changelogs
   126              jq -r '"\(.repo) \(.new // "origin/master") \(.old // "")"' |
   127              while read repo new old; do
   128                  local changelog="$(release_log "$repo" "$old" "$new")"
   129                  if [[ -n "$changelog" ]]; then
   130                      printf "- %s:\n" "$repo"
   131                      echo "$changelog" | indent
   132                  fi
   133              done
   134      )
   135  }
   136  
   137  recursive_release_log "$@"