mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 02:57:26 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			257 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			257 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/bin/zsh
 | 
						|
#set -x
 | 
						|
set -euo pipefail
 | 
						|
export GO111MODULE=on
 | 
						|
export GOPATH="$(go env GOPATH)"
 | 
						|
 | 
						|
alias jq="jq --unbuffered"
 | 
						|
 | 
						|
AUTHORS=(
 | 
						|
    # orgs
 | 
						|
    ipfs
 | 
						|
    ipld
 | 
						|
    libp2p
 | 
						|
    multiformats
 | 
						|
    filecoin-project
 | 
						|
    ipfs-shipyard
 | 
						|
 | 
						|
    # Authors of personal repos used by go-libp2p that should be mentioned in the
 | 
						|
    # release notes.
 | 
						|
    whyrusleeping
 | 
						|
    Kubuxu
 | 
						|
    jbenet
 | 
						|
    Stebalien
 | 
						|
    marten-seemann
 | 
						|
    hsanjuan
 | 
						|
    lucas-clemente
 | 
						|
    warpfork
 | 
						|
)
 | 
						|
 | 
						|
[[ -n "${REPO_FILTER+x}" ]] || REPO_FILTER="github.com/(${$(printf "|%s" "${AUTHORS[@]}"):1})"
 | 
						|
 | 
						|
[[ -n "${IGNORED_FILES+x}" ]] || IGNORED_FILES='^\(\.gx\|package\.json\|\.travis\.yml\|go.mod\|go\.sum|\.github|\.circleci|\.gen\.go\)$'
 | 
						|
 | 
						|
NL=$'\n'
 | 
						|
 | 
						|
ROOT_DIR="$(git rev-parse --show-toplevel)"
 | 
						|
 | 
						|
msg() {
 | 
						|
    echo "$*" >&2
 | 
						|
}
 | 
						|
 | 
						|
statlog() {
 | 
						|
    local module="$1"
 | 
						|
    local rpath="$GOPATH/src/$(strip_version "$module")"
 | 
						|
    local start="${2:-}"
 | 
						|
    local end="${3:-HEAD}"
 | 
						|
    local mailmap_file="$rpath/.mailmap"
 | 
						|
    if ! [[ -e "$mailmap_file" ]]; then
 | 
						|
        mailmap_file="$ROOT_DIR/.mailmap"
 | 
						|
    fi
 | 
						|
 | 
						|
    git -C "$rpath" -c mailmap.file="$mailmap_file" log --use-mailmap --shortstat --no-merges --pretty="tformat:%H%n%aN%n%aE" "$start..$end" | while 
 | 
						|
        read hash
 | 
						|
        read name
 | 
						|
        read email
 | 
						|
        read _ # empty line
 | 
						|
        read changes
 | 
						|
    do
 | 
						|
        if [[ $name == "web3-bot" ]]; then
 | 
						|
            continue
 | 
						|
        fi
 | 
						|
        changed=0
 | 
						|
        insertions=0
 | 
						|
        deletions=0
 | 
						|
        while read count event; do
 | 
						|
            if [[ "$event" =~ ^file ]]; then
 | 
						|
                changed=$count
 | 
						|
            elif [[ "$event" =~ ^insertion ]]; then
 | 
						|
                insertions=$count
 | 
						|
            elif [[ "$event" =~ ^deletion ]]; then
 | 
						|
                deletions=$count
 | 
						|
            else
 | 
						|
                echo "unknown event $event" >&2
 | 
						|
                exit 1
 | 
						|
            fi
 | 
						|
        done<<<"${changes//,/$NL}"
 | 
						|
 | 
						|
        jq -n \
 | 
						|
           --arg "hash" "$hash" \
 | 
						|
           --arg "name" "$name" \
 | 
						|
           --arg "email" "$email" \
 | 
						|
           --argjson "changed" "$changed" \
 | 
						|
           --argjson "insertions" "$insertions" \
 | 
						|
           --argjson "deletions" "$deletions" \
 | 
						|
           '{Commit: $hash, Author: $name, Email: $email, Files: $changed, Insertions: $insertions, Deletions: $deletions}'
 | 
						|
    done
 | 
						|
}
 | 
						|
 | 
						|
# Returns a stream of deps changed between $1 and $2.
 | 
						|
dep_changes() {
 | 
						|
    {
 | 
						|
        <"$1"
 | 
						|
        <"$2"
 | 
						|
    } | jq -s 'JOIN(INDEX(.[0][]; .Path); .[1][]; .Path; {Path: .[0].Path, Old: (.[1] | del(.Path)), New: (.[0] | del(.Path))}) | select(.New.Version != .Old.Version)'
 | 
						|
}
 | 
						|
 | 
						|
# resolve_commits resolves a git ref for each version.
 | 
						|
resolve_commits() {
 | 
						|
    jq '. + {Ref: (.Version|capture("^((?<ref1>.*)\\+incompatible|v.*-(0\\.)?[0-9]{14}-(?<ref2>[a-f0-9]{12})|(?<ref3>v.*))$") | .ref1 // .ref2 // .ref3)}'
 | 
						|
}
 | 
						|
 | 
						|
pr_link() {
 | 
						|
    local repo="$1"
 | 
						|
    local prnum="$2"
 | 
						|
    local ghname="${repo##github.com/}"
 | 
						|
    printf -- "[%s#%s](https://%s/pull/%s)" "$ghname" "$prnum" "$repo" "$prnum"
 | 
						|
}
 | 
						|
 | 
						|
# Generate a release log for a range of commits in a single repo.
 | 
						|
release_log() {
 | 
						|
    setopt local_options BASH_REMATCH
 | 
						|
 | 
						|
    local module="$1"
 | 
						|
    local start="$2"
 | 
						|
    local end="${3:-HEAD}"
 | 
						|
    local repo="$(strip_version "$1")"
 | 
						|
    local dir="$GOPATH/src/$repo"
 | 
						|
 | 
						|
    local commit pr
 | 
						|
    git -C "$dir" log \
 | 
						|
        --format='tformat:%H %s' \
 | 
						|
        --first-parent \
 | 
						|
        "$start..$end" |
 | 
						|
        while read commit subject; do
 | 
						|
            # Skip gx-only PRs.
 | 
						|
            if git rev-parse '$commit^' >/dev/null 2>&1 &&
 | 
						|
                   ! git -C "$dir" diff-tree --no-commit-id --name-only "$commit^" "$commit" | grep -v "${IGNORED_FILES}" >/dev/null; then
 | 
						|
                continue
 | 
						|
            fi
 | 
						|
 | 
						|
            if [[ "$subject" =~ "^sync: update CI config files" ]]; then
 | 
						|
                continue
 | 
						|
            fi
 | 
						|
 | 
						|
            if [[ "$subject" =~ '^Merge pull request #([0-9]+) from' ]]; then
 | 
						|
                local prnum="${BASH_REMATCH[2]}"
 | 
						|
                local desc="$(git -C "$dir" show --summary --format='tformat:%b' "$commit" | head -1)"
 | 
						|
                if [[ "$desc" =~ "^sync: update CI config files" ]]; then
 | 
						|
                    continue
 | 
						|
                fi
 | 
						|
                printf -- "- %s (%s)\n" "$desc" "$(pr_link "$repo" "$prnum")"
 | 
						|
            elif [[ "$subject" =~ '\(#([0-9]+)\)$' ]]; then
 | 
						|
                local prnum="${BASH_REMATCH[2]}"
 | 
						|
                printf -- "- %s (%s)\n" "$subject" "$(pr_link "$repo" "$prnum")"
 | 
						|
            else
 | 
						|
                printf -- "- %s\n" "$subject"
 | 
						|
            fi
 | 
						|
        done
 | 
						|
}
 | 
						|
 | 
						|
indent() {
 | 
						|
    sed -e 's/^/  /'
 | 
						|
}
 | 
						|
 | 
						|
mod_deps() {
 | 
						|
    go list -mod=mod -json -m all | jq 'select(.Version != null)'
 | 
						|
}
 | 
						|
 | 
						|
ensure() {
 | 
						|
    local repo="$(strip_version "$1")"
 | 
						|
    local commit="$2"
 | 
						|
    local rpath="$GOPATH/src/$repo"
 | 
						|
    if [[ ! -d "$rpath" ]]; then
 | 
						|
        msg "Cloning $repo..."
 | 
						|
        git clone "http://$repo" "$rpath" >&2
 | 
						|
    fi
 | 
						|
 | 
						|
    if ! git -C "$rpath" rev-parse --verify "$commit" >/dev/null; then
 | 
						|
        msg "Fetching $repo..."
 | 
						|
        git -C "$rpath" fetch --all >&2
 | 
						|
    fi
 | 
						|
 | 
						|
    git -C "$rpath" rev-parse --verify "$commit" >/dev/null || return 1
 | 
						|
}
 | 
						|
 | 
						|
statsummary() {
 | 
						|
    jq -s 'group_by(.Author)[] | {Author: .[0].Author, Commits: (. | length), Insertions: (map(.Insertions) | add), Deletions: (map(.Deletions) | add), Files: (map(.Files) | add)}' |
 | 
						|
        jq '. + {Lines: (.Deletions + .Insertions)}'
 | 
						|
}
 | 
						|
 | 
						|
strip_version() {
 | 
						|
    local repo="$1"
 | 
						|
    if [[ "$repo" =~ '.*/v[0-9]+$' ]]; then
 | 
						|
        repo="$(dirname "$repo")"
 | 
						|
    fi
 | 
						|
    echo "$repo"
 | 
						|
}
 | 
						|
 | 
						|
recursive_release_log() {
 | 
						|
    local start="${1:-$(git tag -l | sort -V | grep -v -- '-rc' | grep 'v'| tail -n1)}"
 | 
						|
    local end="${2:-$(git rev-parse HEAD)}"
 | 
						|
    local repo_root="$(git rev-parse --show-toplevel)"
 | 
						|
    local module="$(go list -m)"
 | 
						|
    local dir="$(go list -m -f '{{.Dir}}')"
 | 
						|
 | 
						|
    if [[ "${GOPATH}/${module}" -ef "${dir}" ]]; then
 | 
						|
        echo "This script requires the target module and all dependencies to live in a GOPATH."
 | 
						|
        return 1
 | 
						|
    fi
 | 
						|
 | 
						|
    (
 | 
						|
        local result=0
 | 
						|
        local workspace="$(mktemp -d)"
 | 
						|
        trap "$(printf 'rm -rf "%q"' "$workspace")" INT TERM EXIT
 | 
						|
        cd "$workspace"
 | 
						|
 | 
						|
        echo "Computing old deps..." >&2
 | 
						|
        git -C "$repo_root" show "$start:go.mod" >go.mod
 | 
						|
        mod_deps | resolve_commits | jq -s > old_deps.json
 | 
						|
 | 
						|
        echo "Computing new deps..." >&2
 | 
						|
        git -C "$repo_root" show "$end:go.mod" >go.mod
 | 
						|
        mod_deps | resolve_commits | jq -s > new_deps.json
 | 
						|
 | 
						|
        rm -f go.mod go.sum
 | 
						|
 | 
						|
        printf -- "Generating Changelog for %s %s..%s\n" "$module" "$start" "$end" >&2
 | 
						|
 | 
						|
        printf -- "- %s:\n" "$module"
 | 
						|
        release_log "$module" "$start" "$end" | indent
 | 
						|
 | 
						|
 | 
						|
        statlog "$module" "$start" "$end" > statlog.json
 | 
						|
 | 
						|
        dep_changes old_deps.json new_deps.json |
 | 
						|
            jq --arg filter "$REPO_FILTER" 'select(.Path | match($filter))' |
 | 
						|
            # Compute changelogs
 | 
						|
            jq -r '"\(.Path) \(.New.Version) \(.New.Ref) \(.Old.Version) \(.Old.Ref // "")"' |
 | 
						|
            while read module new new_ref old old_ref; do
 | 
						|
                if ! ensure "$module" "$new_ref"; then
 | 
						|
                    result=1
 | 
						|
                    local changelog="failed to fetch repo"
 | 
						|
                else
 | 
						|
                    statlog "$module" "$old_ref" "$new_ref" >> statlog.json
 | 
						|
                    local changelog="$(release_log "$module" "$old_ref" "$new_ref")"
 | 
						|
                fi
 | 
						|
                if [[ -n "$changelog" ]]; then
 | 
						|
                    printf -- "- %s (%s -> %s):\n" "$module" "$old" "$new"
 | 
						|
                    echo "$changelog" | indent
 | 
						|
                fi
 | 
						|
            done
 | 
						|
 | 
						|
        echo
 | 
						|
        echo "Contributors"
 | 
						|
        echo
 | 
						|
 | 
						|
        echo "| Contributor | Commits | Lines ± | Files Changed |"
 | 
						|
        echo "|-------------|---------|---------|---------------|"
 | 
						|
        statsummary <statlog.json |
 | 
						|
            jq -s 'sort_by(.Lines) | reverse | .[]' |
 | 
						|
            jq -r '"| \(.Author) | \(.Commits) | +\(.Insertions)/-\(.Deletions) | \(.Files) |"'
 | 
						|
        return "$status"
 | 
						|
    )
 | 
						|
}
 | 
						|
 | 
						|
recursive_release_log "$@"
 |