mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 10:27:46 +08:00
Merge pull request #11080 from ipfs/merge-release-v0.39.0
Some checks are pending
CodeQL / codeql (push) Waiting to run
Docker Check / lint (push) Waiting to run
Docker Check / build (push) Waiting to run
Gateway Conformance / gateway-conformance (push) Waiting to run
Gateway Conformance / gateway-conformance-libp2p-experiment (push) Waiting to run
Go Build / go-build (push) Waiting to run
Go Check / go-check (push) Waiting to run
Go Lint / go-lint (push) Waiting to run
Go Test / go-test (push) Waiting to run
Interop / interop-prep (push) Waiting to run
Interop / helia-interop (push) Blocked by required conditions
Interop / ipfs-webui (push) Blocked by required conditions
Sharness / sharness-test (push) Waiting to run
Spell Check / spellcheck (push) Waiting to run
Some checks are pending
CodeQL / codeql (push) Waiting to run
Docker Check / lint (push) Waiting to run
Docker Check / build (push) Waiting to run
Gateway Conformance / gateway-conformance (push) Waiting to run
Gateway Conformance / gateway-conformance-libp2p-experiment (push) Waiting to run
Go Build / go-build (push) Waiting to run
Go Check / go-check (push) Waiting to run
Go Lint / go-lint (push) Waiting to run
Go Test / go-test (push) Waiting to run
Interop / interop-prep (push) Waiting to run
Interop / helia-interop (push) Blocked by required conditions
Interop / ipfs-webui (push) Blocked by required conditions
Sharness / sharness-test (push) Waiting to run
Spell Check / spellcheck (push) Waiting to run
Merge release v0.39.0
This commit is contained in:
commit
f7db0c4fc1
532
bin/mkreleaselog
532
bin/mkreleaselog
@ -1,10 +1,19 @@
|
||||
#!/bin/zsh
|
||||
#!/bin/bash
|
||||
#
|
||||
# Invocation: mkreleaselog [FIRST_REF [LAST_REF]]
|
||||
#
|
||||
# Generates release notes with contributor statistics, deduplicating by GitHub handle.
|
||||
# GitHub handles are resolved from:
|
||||
# 1. GitHub noreply emails (user@users.noreply.github.com)
|
||||
# 2. Merge commit messages (Merge pull request #N from user/branch)
|
||||
# 3. GitHub API via gh CLI (for squash merges)
|
||||
#
|
||||
# Results are cached in ~/.cache/mkreleaselog/github-handles.json
|
||||
|
||||
set -euo pipefail
|
||||
export GO111MODULE=on
|
||||
export GOPATH="$(go env GOPATH)"
|
||||
GOPATH="$(go env GOPATH)"
|
||||
export GOPATH
|
||||
|
||||
# List of PCRE regular expressions to match "included" modules.
|
||||
INCLUDE_MODULES=(
|
||||
@ -15,10 +24,15 @@ INCLUDE_MODULES=(
|
||||
"^github.com/multiformats/"
|
||||
"^github.com/filecoin-project/"
|
||||
"^github.com/ipfs-shipyard/"
|
||||
"^github.com/ipshipyard/"
|
||||
"^github.com/probe-lab/"
|
||||
|
||||
# Authors of personal modules used by go-ipfs that should be mentioned in the
|
||||
# release notes.
|
||||
"^github.com/whyrusleeping/"
|
||||
"^github.com/gammazero/"
|
||||
"^github.com/Jorropo/"
|
||||
"^github.com/guillaumemichel/"
|
||||
"^github.com/Kubuxu/"
|
||||
"^github.com/jbenet/"
|
||||
"^github.com/Stebalien/"
|
||||
@ -48,15 +62,348 @@ IGNORE_FILES=(
|
||||
)
|
||||
|
||||
##########################################################################################
|
||||
# GitHub Handle Resolution Infrastructure
|
||||
##########################################################################################
|
||||
|
||||
# Cache location following XDG spec
|
||||
GITHUB_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/mkreleaselog"
|
||||
GITHUB_CACHE_FILE="$GITHUB_CACHE_DIR/github-handles.json"
|
||||
|
||||
# Timeout for gh CLI commands (seconds)
|
||||
GH_TIMEOUT=10
|
||||
|
||||
# Associative array for email -> github handle mapping (runtime cache)
|
||||
declare -A EMAIL_TO_GITHUB
|
||||
|
||||
# Check if gh CLI is available and authenticated
|
||||
gh_available() {
|
||||
command -v gh >/dev/null 2>&1 && gh auth status >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Load cached email -> github handle mappings from disk
|
||||
load_github_cache() {
|
||||
EMAIL_TO_GITHUB=()
|
||||
|
||||
if [[ ! -f "$GITHUB_CACHE_FILE" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Validate JSON before loading
|
||||
if ! jq -e '.' "$GITHUB_CACHE_FILE" >/dev/null 2>&1; then
|
||||
msg "Warning: corrupted cache file, ignoring"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local email handle
|
||||
while IFS=$'\t' read -r email handle; do
|
||||
# Validate handle format (alphanumeric, hyphens, max 39 chars)
|
||||
if [[ -n "$email" && -n "$handle" && "$handle" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$ ]]; then
|
||||
EMAIL_TO_GITHUB["$email"]="$handle"
|
||||
fi
|
||||
done < <(jq -r 'to_entries[] | "\(.key)\t\(.value)"' "$GITHUB_CACHE_FILE" 2>/dev/null)
|
||||
|
||||
msg "Loaded ${#EMAIL_TO_GITHUB[@]} cached GitHub handle mappings"
|
||||
}
|
||||
|
||||
# Save email -> github handle mappings to disk (atomic write)
|
||||
save_github_cache() {
|
||||
if [[ ${#EMAIL_TO_GITHUB[@]} -eq 0 ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "$GITHUB_CACHE_DIR"
|
||||
|
||||
local tmp_file
|
||||
tmp_file="$(mktemp "$GITHUB_CACHE_DIR/cache.XXXXXX")" || return 1
|
||||
|
||||
# Build JSON from associative array
|
||||
{
|
||||
echo "{"
|
||||
local first=true
|
||||
local key
|
||||
for key in "${!EMAIL_TO_GITHUB[@]}"; do
|
||||
if [[ "$first" == "true" ]]; then
|
||||
first=false
|
||||
else
|
||||
echo ","
|
||||
fi
|
||||
# Escape special characters in email for JSON
|
||||
printf ' %s: %s' "$(jq -n --arg e "$key" '$e')" "$(jq -n --arg h "${EMAIL_TO_GITHUB[$key]}" '$h')"
|
||||
done
|
||||
echo
|
||||
echo "}"
|
||||
} > "$tmp_file"
|
||||
|
||||
# Validate before replacing
|
||||
if jq -e '.' "$tmp_file" >/dev/null 2>&1; then
|
||||
mv "$tmp_file" "$GITHUB_CACHE_FILE"
|
||||
msg "Saved ${#EMAIL_TO_GITHUB[@]} GitHub handle mappings to cache"
|
||||
else
|
||||
rm -f "$tmp_file"
|
||||
msg "Warning: failed to save cache (invalid JSON)"
|
||||
fi
|
||||
}
|
||||
|
||||
# Extract GitHub handle from email if it's a GitHub noreply address
|
||||
# Handles: user@users.noreply.github.com and 12345678+user@users.noreply.github.com
|
||||
extract_handle_from_noreply() {
|
||||
local email="$1"
|
||||
|
||||
if [[ "$email" =~ ^([0-9]+\+)?([a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?)@users\.noreply\.github\.com$ ]]; then
|
||||
echo "${BASH_REMATCH[2]}"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Extract GitHub handle from merge commit subject
|
||||
# Handles: "Merge pull request #123 from username/branch"
|
||||
extract_handle_from_merge_commit() {
|
||||
local subject="$1"
|
||||
|
||||
if [[ "$subject" =~ ^Merge\ pull\ request\ \#[0-9]+\ from\ ([a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?)/.*$ ]]; then
|
||||
echo "${BASH_REMATCH[1]}"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Extract PR number from commit subject
|
||||
# Handles: "Subject (#123)" and "Merge pull request #123 from"
|
||||
extract_pr_number() {
|
||||
local subject="$1"
|
||||
|
||||
if [[ "$subject" =~ \(#([0-9]+)\)$ ]]; then
|
||||
echo "${BASH_REMATCH[1]}"
|
||||
return 0
|
||||
elif [[ "$subject" =~ ^Merge\ pull\ request\ \#([0-9]+)\ from ]]; then
|
||||
echo "${BASH_REMATCH[1]}"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Query GitHub API for PR author (with timeout and error handling)
|
||||
query_pr_author() {
|
||||
local gh_repo="$1" # e.g., "ipfs/kubo"
|
||||
local pr_num="$2"
|
||||
|
||||
if ! gh_available; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local handle
|
||||
handle="$(timeout "$GH_TIMEOUT" gh pr view "$pr_num" --repo "$gh_repo" --json author -q '.author.login' 2>/dev/null)" || return 1
|
||||
|
||||
# Validate handle format
|
||||
if [[ -n "$handle" && "$handle" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$ ]]; then
|
||||
echo "$handle"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Query GitHub API for commit author (fallback when no PR available)
|
||||
query_commit_author() {
|
||||
local gh_repo="$1" # e.g., "ipfs/kubo"
|
||||
local commit_sha="$2"
|
||||
|
||||
if ! gh_available; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
local handle
|
||||
handle="$(timeout "$GH_TIMEOUT" gh api "/repos/$gh_repo/commits/$commit_sha" --jq '.author.login // empty' 2>/dev/null)" || return 1
|
||||
|
||||
# Validate handle format
|
||||
if [[ -n "$handle" && "$handle" =~ ^[a-zA-Z0-9]([a-zA-Z0-9-]{0,37}[a-zA-Z0-9])?$ ]]; then
|
||||
echo "$handle"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# Resolve email to GitHub handle using all available methods
|
||||
# Args: email, commit_hash (optional), repo_dir (optional), gh_repo (optional)
|
||||
resolve_github_handle() {
|
||||
local email="$1"
|
||||
local commit="${2:-}"
|
||||
local repo_dir="${3:-}"
|
||||
local gh_repo="${4:-}"
|
||||
|
||||
# Skip empty emails
|
||||
[[ -z "$email" ]] && return 1
|
||||
|
||||
# Check runtime cache first
|
||||
if [[ -n "${EMAIL_TO_GITHUB[$email]:-}" ]]; then
|
||||
echo "${EMAIL_TO_GITHUB[$email]}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local handle=""
|
||||
|
||||
# Method 1: Extract from noreply email
|
||||
if handle="$(extract_handle_from_noreply "$email")"; then
|
||||
EMAIL_TO_GITHUB["$email"]="$handle"
|
||||
echo "$handle"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Method 2: Look at commit message for merge commit pattern
|
||||
if [[ -n "$commit" && -n "$repo_dir" ]]; then
|
||||
local subject
|
||||
subject="$(git -C "$repo_dir" log -1 --format='%s' "$commit" 2>/dev/null)" || true
|
||||
|
||||
if [[ -n "$subject" ]]; then
|
||||
if handle="$(extract_handle_from_merge_commit "$subject")"; then
|
||||
EMAIL_TO_GITHUB["$email"]="$handle"
|
||||
echo "$handle"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Method 3: Query GitHub API for PR author
|
||||
if [[ -n "$gh_repo" ]]; then
|
||||
local pr_num
|
||||
if pr_num="$(extract_pr_number "$subject")"; then
|
||||
if handle="$(query_pr_author "$gh_repo" "$pr_num")"; then
|
||||
EMAIL_TO_GITHUB["$email"]="$handle"
|
||||
echo "$handle"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Build GitHub handle mappings for all commits in a range
|
||||
# This does a single pass to collect PR numbers, then batch queries them
|
||||
build_github_mappings() {
|
||||
local module="$1"
|
||||
local start="$2"
|
||||
local end="${3:-HEAD}"
|
||||
local repo
|
||||
repo="$(strip_version "$module")"
|
||||
local dir
|
||||
local gh_repo=""
|
||||
|
||||
if [[ "$module" == "github.com/ipfs/kubo" ]]; then
|
||||
dir="$ROOT_DIR"
|
||||
else
|
||||
dir="$GOPATH/src/$repo"
|
||||
fi
|
||||
|
||||
# Extract gh_repo for API calls (e.g., "ipfs/kubo" from "github.com/ipfs/kubo")
|
||||
if [[ "$repo" =~ ^github\.com/(.+)$ ]]; then
|
||||
gh_repo="${BASH_REMATCH[1]}"
|
||||
fi
|
||||
|
||||
msg "Building GitHub handle mappings for $module..."
|
||||
|
||||
# Collect all unique emails and their commit context
|
||||
declare -A email_commits=()
|
||||
local hash email subject
|
||||
|
||||
while IFS=$'\t' read -r hash email subject; do
|
||||
[[ -z "$email" ]] && continue
|
||||
|
||||
# Skip if already resolved
|
||||
[[ -n "${EMAIL_TO_GITHUB[$email]:-}" ]] && continue
|
||||
|
||||
# Try to resolve without API first
|
||||
local handle=""
|
||||
|
||||
# Method 1: noreply email
|
||||
if handle="$(extract_handle_from_noreply "$email")"; then
|
||||
EMAIL_TO_GITHUB["$email"]="$handle"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Method 2: merge commit message
|
||||
if handle="$(extract_handle_from_merge_commit "$subject")"; then
|
||||
EMAIL_TO_GITHUB["$email"]="$handle"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Store for potential API lookup
|
||||
if [[ -z "${email_commits[$email]:-}" ]]; then
|
||||
email_commits["$email"]="$hash"
|
||||
fi
|
||||
done < <(git -C "$dir" log --format='tformat:%H%x09%aE%x09%s' --no-merges "$start..$end" 2>/dev/null)
|
||||
|
||||
# API batch lookup for remaining emails (if gh is available)
|
||||
if gh_available && [[ -n "$gh_repo" && ${#email_commits[@]} -gt 0 ]]; then
|
||||
msg "Querying GitHub API for ${#email_commits[@]} unknown contributors..."
|
||||
local key
|
||||
for key in "${!email_commits[@]}"; do
|
||||
# Skip if already resolved
|
||||
[[ -n "${EMAIL_TO_GITHUB[$key]:-}" ]] && continue
|
||||
|
||||
local commit_hash="${email_commits[$key]}"
|
||||
local subj handle
|
||||
subj="$(git -C "$dir" log -1 --format='%s' "$commit_hash" 2>/dev/null)" || true
|
||||
|
||||
# Try PR author lookup first (cheaper API call)
|
||||
local pr_num
|
||||
if pr_num="$(extract_pr_number "$subj")"; then
|
||||
if handle="$(query_pr_author "$gh_repo" "$pr_num")"; then
|
||||
EMAIL_TO_GITHUB["$key"]="$handle"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fallback: commit author API (works for any commit)
|
||||
if handle="$(query_commit_author "$gh_repo" "$commit_hash")"; then
|
||||
EMAIL_TO_GITHUB["$key"]="$handle"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
##########################################################################################
|
||||
# Original infrastructure with modifications
|
||||
##########################################################################################
|
||||
|
||||
build_include_regex() {
|
||||
local result=""
|
||||
local mod
|
||||
for mod in "${INCLUDE_MODULES[@]}"; do
|
||||
if [[ -n "$result" ]]; then
|
||||
result="$result|$mod"
|
||||
else
|
||||
result="$mod"
|
||||
fi
|
||||
done
|
||||
echo "($result)"
|
||||
}
|
||||
|
||||
build_exclude_regex() {
|
||||
local result=""
|
||||
local mod
|
||||
for mod in "${EXCLUDE_MODULES[@]}"; do
|
||||
if [[ -n "$result" ]]; then
|
||||
result="$result|$mod"
|
||||
else
|
||||
result="$mod"
|
||||
fi
|
||||
done
|
||||
if [[ -n "$result" ]]; then
|
||||
echo "($result)"
|
||||
else
|
||||
echo '$^' # match nothing
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ ${#INCLUDE_MODULES[@]} -gt 0 ]]; then
|
||||
INCLUDE_REGEX="(${$(printf "|%s" "${INCLUDE_MODULES[@]}"):1})"
|
||||
INCLUDE_REGEX="$(build_include_regex)"
|
||||
else
|
||||
INCLUDE_REGEX="" # "match anything"
|
||||
fi
|
||||
|
||||
if [[ ${#EXCLUDE_MODULES[@]} -gt 0 ]]; then
|
||||
EXCLUDE_REGEX="(${$(printf "|%s" "${EXCLUDE_MODULES[@]}"):1})"
|
||||
EXCLUDE_REGEX="$(build_exclude_regex)"
|
||||
else
|
||||
EXCLUDE_REGEX='$^' # "match nothing"
|
||||
fi
|
||||
@ -71,8 +418,6 @@ NL=$'\n'
|
||||
|
||||
ROOT_DIR="$(git rev-parse --show-toplevel)"
|
||||
|
||||
alias jq="jq --unbuffered"
|
||||
|
||||
msg() {
|
||||
echo "$*" >&2
|
||||
}
|
||||
@ -80,11 +425,21 @@ msg() {
|
||||
statlog() {
|
||||
local module="$1"
|
||||
local rpath
|
||||
local gh_repo=""
|
||||
|
||||
if [[ "$module" == "github.com/ipfs/kubo" ]]; then
|
||||
rpath="$ROOT_DIR"
|
||||
else
|
||||
rpath="$GOPATH/src/$(strip_version "$module")"
|
||||
fi
|
||||
|
||||
# Extract gh_repo for API calls
|
||||
local repo
|
||||
repo="$(strip_version "$module")"
|
||||
if [[ "$repo" =~ ^github\.com/(.+)$ ]]; then
|
||||
gh_repo="${BASH_REMATCH[1]}"
|
||||
fi
|
||||
|
||||
local start="${2:-}"
|
||||
local end="${3:-HEAD}"
|
||||
local mailmap_file="$rpath/.mailmap"
|
||||
@ -93,18 +448,21 @@ statlog() {
|
||||
fi
|
||||
|
||||
local stack=()
|
||||
git -C "$rpath" -c mailmap.file="$mailmap_file" log --use-mailmap --shortstat --no-merges --pretty="tformat:%H%x09%aN%x09%aE" "$start..$end" -- . "${IGNORE_FILES_PATHSPEC[@]}" | while read -r line; do
|
||||
local line
|
||||
while read -r line; do
|
||||
if [[ -n "$line" ]]; then
|
||||
stack+=("$line")
|
||||
continue
|
||||
fi
|
||||
|
||||
local changes
|
||||
read -r changes
|
||||
|
||||
changed=0
|
||||
insertions=0
|
||||
deletions=0
|
||||
while read count event; do
|
||||
local changed=0
|
||||
local insertions=0
|
||||
local deletions=0
|
||||
local count event
|
||||
while read -r count event; do
|
||||
if [[ "$event" =~ ^file ]]; then
|
||||
changed=$count
|
||||
elif [[ "$event" =~ ^insertion ]]; then
|
||||
@ -117,27 +475,32 @@ statlog() {
|
||||
fi
|
||||
done<<<"${changes//,/$NL}"
|
||||
|
||||
local author
|
||||
for author in "${stack[@]}"; do
|
||||
local hash name email
|
||||
IFS=$'\t' read -r hash name email <<<"$author"
|
||||
|
||||
# Resolve GitHub handle
|
||||
local github_handle=""
|
||||
github_handle="$(resolve_github_handle "$email" "$hash" "$rpath" "$gh_repo")" || true
|
||||
|
||||
jq -n \
|
||||
--arg "hash" "$hash" \
|
||||
--arg "name" "$name" \
|
||||
--arg "email" "$email" \
|
||||
--arg "github" "$github_handle" \
|
||||
--argjson "changed" "$changed" \
|
||||
--argjson "insertions" "$insertions" \
|
||||
--argjson "deletions" "$deletions" \
|
||||
'{Commit: $hash, Author: $name, Email: $email, Files: $changed, Insertions: $insertions, Deletions: $deletions}'
|
||||
'{Commit: $hash, Author: $name, Email: $email, GitHub: $github, Files: $changed, Insertions: $insertions, Deletions: $deletions}'
|
||||
done
|
||||
stack=()
|
||||
done
|
||||
done < <(git -C "$rpath" -c mailmap.file="$mailmap_file" log --use-mailmap --shortstat --no-merges --pretty="tformat:%H%x09%aN%x09%aE" "$start..$end" -- . "${IGNORE_FILES_PATHSPEC[@]}")
|
||||
}
|
||||
|
||||
# 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)'
|
||||
cat "$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.
|
||||
@ -165,12 +528,11 @@ ignored_commit() {
|
||||
|
||||
# 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 repo
|
||||
repo="$(strip_version "$1")"
|
||||
local dir
|
||||
if [[ "$module" == "github.com/ipfs/kubo" ]]; then
|
||||
dir="$ROOT_DIR"
|
||||
@ -178,28 +540,25 @@ release_log() {
|
||||
dir="$GOPATH/src/$repo"
|
||||
fi
|
||||
|
||||
local commit pr
|
||||
git -C "$dir" log \
|
||||
--format='tformat:%H %s' \
|
||||
--first-parent \
|
||||
"$start..$end" |
|
||||
while read commit subject; do
|
||||
# Skip commits that only touch ignored files.
|
||||
if ignored_commit "$dir" "$commit"; then
|
||||
continue
|
||||
fi
|
||||
local commit subject
|
||||
while read -r commit subject; do
|
||||
# Skip commits that only touch ignored files.
|
||||
if ignored_commit "$dir" "$commit"; 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)"
|
||||
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
|
||||
if [[ "$subject" =~ ^Merge\ pull\ request\ \#([0-9]+)\ from ]]; then
|
||||
local prnum="${BASH_REMATCH[1]}"
|
||||
local desc
|
||||
desc="$(git -C "$dir" show --summary --format='tformat:%b' "$commit" | head -1)"
|
||||
printf -- "- %s (%s)\n" "$desc" "$(pr_link "$repo" "$prnum")"
|
||||
elif [[ "$subject" =~ \(#([0-9]+)\)$ ]]; then
|
||||
local prnum="${BASH_REMATCH[1]}"
|
||||
printf -- "- %s (%s)\n" "$subject" "$(pr_link "$repo" "$prnum")"
|
||||
else
|
||||
printf -- "- %s\n" "$subject"
|
||||
fi
|
||||
done < <(git -C "$dir" log --format='tformat:%H %s' --first-parent "$start..$end")
|
||||
}
|
||||
|
||||
indent() {
|
||||
@ -211,7 +570,8 @@ mod_deps() {
|
||||
}
|
||||
|
||||
ensure() {
|
||||
local repo="$(strip_version "$1")"
|
||||
local repo
|
||||
repo="$(strip_version "$1")"
|
||||
local commit="$2"
|
||||
local rpath
|
||||
if [[ "$1" == "github.com/ipfs/kubo" ]]; then
|
||||
@ -232,14 +592,27 @@ ensure() {
|
||||
git -C "$rpath" rev-parse --verify "$commit" >/dev/null || return 1
|
||||
}
|
||||
|
||||
# Summarize stats, grouping by GitHub handle (with fallback to email for dedup)
|
||||
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)}'
|
||||
jq -s '
|
||||
# Group by GitHub handle if available, otherwise by email
|
||||
group_by(if .GitHub != "" then .GitHub else .Email end)[] |
|
||||
{
|
||||
# Use first non-empty GitHub handle, or fall back to Author name
|
||||
Author: .[0].Author,
|
||||
GitHub: (map(select(.GitHub != "")) | .[0].GitHub // ""),
|
||||
Email: .[0].Email,
|
||||
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
|
||||
if [[ "$repo" =~ .*/v[0-9]+$ ]]; then
|
||||
repo="$(dirname "$repo")"
|
||||
fi
|
||||
echo "$repo"
|
||||
@ -248,16 +621,24 @@ strip_version() {
|
||||
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}}')"
|
||||
local repo_root
|
||||
repo_root="$(git rev-parse --show-toplevel)"
|
||||
local module
|
||||
module="$(go list -m)"
|
||||
local dir
|
||||
dir="$(go list -m -f '{{.Dir}}')"
|
||||
|
||||
# Load cached GitHub handle mappings
|
||||
load_github_cache
|
||||
|
||||
# Kubo can be run from any directory, dependencies still use GOPATH
|
||||
|
||||
(
|
||||
local result=0
|
||||
local workspace="$(mktemp -d)"
|
||||
trap "$(printf 'rm -rf "%q"' "$workspace")" INT TERM EXIT
|
||||
local workspace
|
||||
workspace="$(mktemp -d)"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '$workspace'" INT TERM EXIT
|
||||
cd "$workspace"
|
||||
|
||||
echo "Computing old deps..." >&2
|
||||
@ -272,6 +653,9 @@ recursive_release_log() {
|
||||
|
||||
printf -- "Generating Changelog for %s %s..%s\n" "$module" "$start" "$end" >&2
|
||||
|
||||
# Pre-build GitHub mappings for main module
|
||||
build_github_mappings "$module" "$start" "$end"
|
||||
|
||||
echo "### 📝 Changelog"
|
||||
echo
|
||||
echo "<details><summary>Full Changelog</summary>"
|
||||
@ -282,24 +666,26 @@ recursive_release_log() {
|
||||
|
||||
statlog "$module" "$start" "$end" > statlog.json
|
||||
|
||||
dep_changes old_deps.json new_deps.json |
|
||||
local dep_module new new_ref old old_ref
|
||||
while read -r dep_module new new_ref old old_ref; do
|
||||
if ! ensure "$dep_module" "$new_ref"; then
|
||||
result=1
|
||||
local changelog="failed to fetch repo"
|
||||
else
|
||||
# Pre-build GitHub mappings for dependency
|
||||
build_github_mappings "$dep_module" "$old_ref" "$new_ref"
|
||||
statlog "$dep_module" "$old_ref" "$new_ref" >> statlog.json
|
||||
local changelog
|
||||
changelog="$(release_log "$dep_module" "$old_ref" "$new_ref")"
|
||||
fi
|
||||
if [[ -n "$changelog" ]]; then
|
||||
printf -- "- %s (%s -> %s):\n" "$dep_module" "$old" "$new"
|
||||
echo "$changelog" | indent
|
||||
fi
|
||||
done < <(dep_changes old_deps.json new_deps.json |
|
||||
jq --arg inc "$INCLUDE_REGEX" --arg exc "$EXCLUDE_REGEX" \
|
||||
'select(.Path | test($inc)) | select(.Path | test($exc) | not)' |
|
||||
# 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
|
||||
jq -r '"\(.Path) \(.New.Version) \(.New.Ref) \(.Old.Version) \(.Old.Ref // "")"')
|
||||
|
||||
echo
|
||||
echo "</details>"
|
||||
@ -311,8 +697,18 @@ recursive_release_log() {
|
||||
echo "|-------------|---------|---------|---------------|"
|
||||
statsummary <statlog.json |
|
||||
jq -s 'sort_by(.Lines) | reverse | .[]' |
|
||||
jq -r '"| \(.Author) | \(.Commits) | +\(.Insertions)/-\(.Deletions) | \(.Files) |"'
|
||||
return "$status"
|
||||
jq -r '
|
||||
if .GitHub != "" then
|
||||
"| [@\(.GitHub)](https://github.com/\(.GitHub)) | \(.Commits) | +\(.Insertions)/-\(.Deletions) | \(.Files) |"
|
||||
else
|
||||
"| \(.Author) | \(.Commits) | +\(.Insertions)/-\(.Deletions) | \(.Files) |"
|
||||
end
|
||||
'
|
||||
|
||||
# Save cache before exiting
|
||||
save_github_cache
|
||||
|
||||
return "$result"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -8,29 +8,33 @@ This release was brought to you by the [Shipyard](https://ipshipyard.com/) team.
|
||||
|
||||
## v0.39.0
|
||||
|
||||
[<img align="right" width="256px" src="https://github.com/user-attachments/assets/427702e8-b6b8-4ac2-8425-18069626c321" />](https://github.com/user-attachments/assets/427702e8-b6b8-4ac2-8425-18069626c321)
|
||||
|
||||
- [Overview](#overview)
|
||||
- [🔦 Highlights](#-highlights)
|
||||
- [🎯 Amino DHT Sweep provider is now the default](#-amino-dht-sweep-provider-is-now-the-default)
|
||||
- [🎯 DHT Sweep provider is now the default](#-dht-sweep-provider-is-now-the-default)
|
||||
- [⚡ Fast root CID providing for immediate content discovery](#-fast-root-cid-providing-for-immediate-content-discovery)
|
||||
- [📊 Detailed statistics for Sweep provider with `ipfs provide stat`](#-detailed-statistics-for-sweep-provider-with-ipfs-provide-stat)
|
||||
- [⏯️ Provider resume cycle for improved reproviding reliability](#provider-resume-cycle-for-improved-reproviding-reliability)
|
||||
- [🔔 Sweep provider slow reprovide warnings](#-sweep-provider-slow-reprovide-warnings)
|
||||
- [⏯️ Provider state persists across restarts](#️-provider-state-persists-across-restarts)
|
||||
- [📊 Detailed statistics with `ipfs provide stat`](#-detailed-statistics-with-ipfs-provide-stat)
|
||||
- [🔔 Slow reprovide warnings](#-slow-reprovide-warnings)
|
||||
- [📊 Metric rename: `provider_provides_total`](#-metric-rename-provider_provides_total)
|
||||
- [🔧 Fixed UPnP port forwarding after router restarts](#-fixed-upnp-port-forwarding-after-router-restarts)
|
||||
- [🖥️ RISC-V support with prebuilt binaries](#️-risc-v-support-with-prebuilt-binaries)
|
||||
- [🚦 Gateway range request limits for CDN compatibility](#-gateway-range-request-limits-for-cdn-compatibility)
|
||||
- [🔧 Automatic UPnP recovery after router restarts](#-automatic-upnp-recovery-after-router-restarts)
|
||||
- [🪦 Deprecated `go-ipfs` name no longer published](#-deprecated-go-ipfs-name-no-longer-published)
|
||||
- [🚦 Gateway range request limits for CDN compatibility](#-gateway-range-request-limits-for-cdn-compatibility)
|
||||
- [🖥️ RISC-V support with prebuilt binaries](#️-risc-v-support-with-prebuilt-binaries)
|
||||
- [📦️ Important dependency updates](#-important-dependency-updates)
|
||||
- [📝 Changelog](#-changelog)
|
||||
- [👨👩👧👦 Contributors](#-contributors)
|
||||
|
||||
### Overview
|
||||
|
||||
Kubo 0.39.0 graduates the experimental sweep provider to default, bringing efficient content announcement to all nodes. This release adds fast root CID providing for immediate content discovery via `ipfs add`, detailed provider statistics, automatic state persistence for reliable reproviding after restarts, and proactive monitoring alerts for identifying issues early. It also includes important fixes for UPnP port forwarding, RISC-V prebuilt binaries, and finalizes the deprecation of the legacy go-ipfs name.
|
||||
Kubo 0.39 makes self-hosting practical on consumer hardware and home networks. The DHT sweep provider (now default) announces your content to the network without traffic spikes that overwhelm residential connections. Automatic UPnP recovery means your node stays reachable after router restarts without manual intervention.
|
||||
|
||||
New content becomes findable immediately after `ipfs add`. The provider system persists state across restarts, alerts you when falling behind, and exposes detailed stats for monitoring. This release also finalizes the deprecation of the legacy `go-ipfs` name.
|
||||
|
||||
### 🔦 Highlights
|
||||
|
||||
#### 🎯 Amino DHT Sweep provider is now the default
|
||||
#### 🎯 DHT Sweep provider is now the default
|
||||
|
||||
The Amino DHT Sweep provider system, introduced as experimental in v0.38, is now enabled by default (`Provide.DHT.SweepEnabled=true`).
|
||||
|
||||
@ -41,16 +45,17 @@ The Amino DHT Sweep provider system, introduced as experimental in v0.38, is now
|
||||
- If you explicitly set `Provide.DHT.SweepEnabled=false` in v0.38, you'll continue using the legacy provider
|
||||
- If you were using the default settings, you'll automatically get the sweep provider
|
||||
- To opt out and return to legacy behavior: `ipfs config --json Provide.DHT.SweepEnabled false`
|
||||
- Providers with medium to large datasets may need to adjust defaults; see [Capacity Planning](https://github.com/ipfs/kubo/blob/master/docs/provide-stats.md#capacity-planning)
|
||||
|
||||
**New features available with sweep mode:**
|
||||
|
||||
- Detailed statistics via `ipfs provide stat` ([see below](#-detailed-statistics-for-sweep-provider-with-ipfs-provide-stat))
|
||||
- Automatic resume after restarts with persistent state ([see below](#provider-resume-cycle-for-improved-reproviding-reliability))
|
||||
- Proactive alerts when reproviding falls behind ([see below](#-sweep-provider-slow-reprovide-warnings))
|
||||
- Detailed statistics via `ipfs provide stat` ([see below](#-detailed-statistics-with-ipfs-provide-stat))
|
||||
- Automatic resume after restarts with persistent state ([see below](#️-provider-state-persists-across-restarts))
|
||||
- Proactive alerts when reproviding falls behind ([see below](#-slow-reprovide-warnings))
|
||||
- Better metrics for monitoring (`provider_provides_total`) ([see below](#-metric-rename-provider_provides_total))
|
||||
- Fast optimistic provide of new root CIDs ([see below](#-fast-root-cid-providing-for-immediate-content-discovery))
|
||||
|
||||
For background on the sweep provider design and motivations, see [`Provide.DHT.SweepEnabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#providedhtsweepenabled) and [ipshipyard.com#8](https://github.com/ipshipyard/ipshipyard.com/pull/8).
|
||||
For background on the sweep provider design and motivations, see [`Provide.DHT.SweepEnabled`](https://github.com/ipfs/kubo/blob/master/docs/config.md#providedhtsweepenabled) and Shipyard's blogpost [Provide Sweep: Solving the DHT Provide Bottleneck](https://ipshipyard.com/blog/2025-dht-provide-sweep/).
|
||||
|
||||
#### ⚡ Fast root CID providing for immediate content discovery
|
||||
|
||||
@ -74,20 +79,7 @@ ipfs dag import file.car # Same for CAR imports
|
||||
|
||||
This optimization works best with the sweep provider and accelerated DHT client, where provide operations are significantly faster. Automatically skipped when DHT is unavailable (e.g., `Routing.Type=none` or delegated-only configurations).
|
||||
|
||||
#### 📊 Detailed statistics for Sweep provider with `ipfs provide stat`
|
||||
|
||||
The Sweep provider system now exposes detailed statistics through `ipfs provide stat`, helping you monitor provider health and troubleshoot issues.
|
||||
|
||||
Run `ipfs provide stat` for a quick summary, or use `--all` to see complete metrics including connectivity status, queue sizes, reprovide schedules, network statistics, operation rates, and worker utilization. For real-time monitoring, use `watch ipfs provide stat --all --compact` to observe changes in a 2-column layout. Individual sections can be displayed with flags like `--network`, `--operations`, or `--workers`.
|
||||
|
||||
For Dual DHT configurations, use `--lan` to view LAN DHT statistics instead of the default WAN DHT stats.
|
||||
|
||||
For more information, run `ipfs provide stat --help` or see the [Provide Stats documentation](https://github.com/ipfs/kubo/blob/master/docs/provide-stats.md).
|
||||
|
||||
> [!NOTE]
|
||||
> Legacy provider (when `Provide.DHT.SweepEnabled=false`) shows basic statistics without flag support.
|
||||
|
||||
#### ⏯️ Provider resume cycle for improved reproviding reliability
|
||||
#### ⏯️ Provider state persists across restarts
|
||||
|
||||
The Sweep provider now persists the reprovide cycle state and automatically resumes where it left off after a restart. This brings several improvements:
|
||||
|
||||
@ -98,7 +90,20 @@ The Sweep provider now persists the reprovide cycle state and automatically resu
|
||||
|
||||
This feature improves reliability for nodes that experience intermittent connectivity or restarts.
|
||||
|
||||
#### 🔔 Sweep provider slow reprovide warnings
|
||||
#### 📊 Detailed statistics with `ipfs provide stat`
|
||||
|
||||
The Sweep provider system now exposes detailed statistics through `ipfs provide stat`, helping you monitor provider health and troubleshoot issues.
|
||||
|
||||
Run `ipfs provide stat` for a quick summary, or use `--all` to see complete metrics including connectivity status, queue sizes, reprovide schedules, network statistics, operation rates, and worker utilization. For real-time monitoring, use `watch ipfs provide stat --all --compact` to observe changes in a 2-column layout. Individual sections can be displayed with flags like `--network`, `--operations`, or `--workers`.
|
||||
|
||||
For Dual DHT configurations, use `--lan` to view LAN DHT statistics instead of the default WAN DHT stats.
|
||||
|
||||
For more information, run `ipfs provide stat --help` or see the [Provide Stats documentation](https://github.com/ipfs/kubo/blob/master/docs/provide-stats.md), including [Capacity Planning](https://github.com/ipfs/kubo/blob/master/docs/provide-stats.md#capacity-planning).
|
||||
|
||||
> [!NOTE]
|
||||
> Legacy provider (when `Provide.DHT.SweepEnabled=false`) shows basic statistics without flag support.
|
||||
|
||||
#### 🔔 Slow reprovide warnings
|
||||
|
||||
Kubo now monitors DHT reprovide operations when `Provide.DHT.SweepEnabled=true`
|
||||
and alerts you if your node is falling behind on reprovides.
|
||||
@ -120,7 +125,7 @@ The Amino DHT Sweep provider metric has been renamed from `total_provide_count_t
|
||||
|
||||
**Migration:** If you have Prometheus queries, dashboards, or alerts monitoring the old `total_provide_count_total` metric, update them to use `provider_provides_total` instead. This affects all nodes using sweep mode, which is now the default in v0.39 (previously opt-in experimental in v0.38).
|
||||
|
||||
#### 🔧 Fixed UPnP port forwarding after router restarts
|
||||
#### 🔧 Automatic UPnP recovery after router restarts
|
||||
|
||||
Kubo now automatically recovers UPnP port mappings when routers restart or
|
||||
become temporarily unavailable, fixing a critical connectivity issue that
|
||||
@ -144,20 +149,6 @@ without manual intervention.
|
||||
This significantly improves reliability for desktop and self-hosted IPFS nodes
|
||||
using UPnP for NAT traversal.
|
||||
|
||||
#### 🖥️ RISC-V support with prebuilt binaries
|
||||
|
||||
Kubo provides official `linux-riscv64` prebuilt binaries, bringing IPFS to [RISC-V](https://en.wikipedia.org/wiki/RISC-V) open hardware.
|
||||
|
||||
As RISC-V single-board computers and embedded systems become more accessible, the distributed web is now supported on open hardware architectures - a natural pairing of open technologies.
|
||||
|
||||
Download from <https://dist.ipfs.tech/kubo/> or <https://github.com/ipfs/kubo/releases> and look for the `linux-riscv64` archive.
|
||||
|
||||
#### 🚦 Gateway range request limits for CDN compatibility
|
||||
|
||||
The new [`Gateway.MaxRangeRequestFileSize`](https://github.com/ipfs/kubo/blob/master/docs/config.md#gatewaymaxrangerequestfilesize) configuration protects against CDN range request limitations that cause bandwidth overcharges on deserialized responses. Some CDNs convert range requests over large files into full file downloads, causing clients requesting small byte ranges to unknowingly download entire multi-gigabyte files.
|
||||
|
||||
This only impacts deserialized responses. Clients using verifiable block requests (`application/vnd.ipld.raw`) are not affected. See the [configuration documentation](https://github.com/ipfs/kubo/blob/master/docs/config.md#gatewaymaxrangerequestfilesize) for details.
|
||||
|
||||
#### 🪦 Deprecated `go-ipfs` name no longer published
|
||||
|
||||
The `go-ipfs` name was deprecated in 2022 and renamed to `kubo`. Starting with this release, the legacy Docker image name has been replaced with a stub that displays an error message directing users to switch to `ipfs/kubo`.
|
||||
@ -168,6 +159,20 @@ The `go-ipfs` name was deprecated in 2022 and renamed to `kubo`. Starting with t
|
||||
|
||||
All users should migrate to the `kubo` name in their scripts and configurations.
|
||||
|
||||
#### 🚦 Gateway range request limits for CDN compatibility
|
||||
|
||||
The new [`Gateway.MaxRangeRequestFileSize`](https://github.com/ipfs/kubo/blob/master/docs/config.md#gatewaymaxrangerequestfilesize) configuration protects against CDN range request limitations that cause bandwidth overcharges on deserialized responses. Some CDNs convert range requests over large files into full file downloads, causing clients requesting small byte ranges to unknowingly download entire multi-gigabyte files.
|
||||
|
||||
This only impacts deserialized responses. Clients using verifiable block requests (`application/vnd.ipld.raw`) are not affected. See the [configuration documentation](https://github.com/ipfs/kubo/blob/master/docs/config.md#gatewaymaxrangerequestfilesize) for details.
|
||||
|
||||
#### 🖥️ RISC-V support with prebuilt binaries
|
||||
|
||||
Kubo provides official `linux-riscv64` prebuilt binaries, bringing IPFS to [RISC-V](https://en.wikipedia.org/wiki/RISC-V) open hardware.
|
||||
|
||||
As RISC-V single-board computers and embedded systems become more accessible, the distributed web is now supported on open hardware architectures - a natural pairing of open technologies.
|
||||
|
||||
Download from <https://dist.ipfs.tech/kubo/> or <https://github.com/ipfs/kubo/releases> and look for the `linux-riscv64` archive.
|
||||
|
||||
### 📦️ Important dependency updates
|
||||
|
||||
- update `go-libp2p` to [v0.45.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.45.0) (incl. [v0.44.0](https://github.com/libp2p/go-libp2p/releases/tag/v0.44.0)) with self-healing UPnP port mappings and go-log/slog interop fixes
|
||||
@ -180,4 +185,179 @@ All users should migrate to the `kubo` name in their scripts and configurations.
|
||||
|
||||
### 📝 Changelog
|
||||
|
||||
<details><summary>Full Changelog</summary>
|
||||
|
||||
- github.com/ipfs/kubo:
|
||||
- docs: mkreleaselog for 0.39
|
||||
- chore: version 0.39.0
|
||||
- bin/mkreleaselog: add github handle resolution and deduplication
|
||||
- docs: restructure v0.39 changelog for clarity
|
||||
- upgrade go-libp2p-kad-dht to v0.36.0 (#11079) ([ipfs/kubo#11079](https://github.com/ipfs/kubo/pull/11079))
|
||||
- fix(docker): include symlinks in scanning for init scripts (#11077) ([ipfs/kubo#11077](https://github.com/ipfs/kubo/pull/11077))
|
||||
- Update deprecation message for Reprovider fields (#11072) ([ipfs/kubo#11072](https://github.com/ipfs/kubo/pull/11072))
|
||||
- chore: release v0.39.0-rc1
|
||||
- test: add regression tests for config secrets protection (#11061) ([ipfs/kubo#11061](https://github.com/ipfs/kubo/pull/11061))
|
||||
- test: add regression tests for API.Authorizations (#11060) ([ipfs/kubo#11060](https://github.com/ipfs/kubo/pull/11060))
|
||||
- test: verifyWorkerRun and helptext (#11063) ([ipfs/kubo#11063](https://github.com/ipfs/kubo/pull/11063))
|
||||
- test(cmdutils): add tests for PathOrCidPath and ValidatePinName (#11062) ([ipfs/kubo#11062](https://github.com/ipfs/kubo/pull/11062))
|
||||
- fix: return original error in PathOrCidPath fallback (#11059) ([ipfs/kubo#11059](https://github.com/ipfs/kubo/pull/11059))
|
||||
- feat: fast provide support in `dag import` (#11058) ([ipfs/kubo#11058](https://github.com/ipfs/kubo/pull/11058))
|
||||
- feat(cli/rpc/add): fast provide of root CID (#11046) ([ipfs/kubo#11046](https://github.com/ipfs/kubo/pull/11046))
|
||||
- feat(telemetry): collect high level provide DHT sweep settings (#11056) ([ipfs/kubo#11056](https://github.com/ipfs/kubo/pull/11056))
|
||||
- feat: enable DHT Provide Sweep by default (#10955) ([ipfs/kubo#10955](https://github.com/ipfs/kubo/pull/10955))
|
||||
- feat(config): optional Gateway.MaxRangeRequestFileSize (#10997) ([ipfs/kubo#10997](https://github.com/ipfs/kubo/pull/10997))
|
||||
- docs: clarify provide stats metric types and calculations (#11041) ([ipfs/kubo#11041](https://github.com/ipfs/kubo/pull/11041))
|
||||
- Upgrade to Boxo v0.35.2 (#11050) ([ipfs/kubo#11050](https://github.com/ipfs/kubo/pull/11050))
|
||||
- fix(go-log@2.9/go-libp2p@0.45): dynamic log level control and tail (#11039) ([ipfs/kubo#11039](https://github.com/ipfs/kubo/pull/11039))
|
||||
- chore: update webui to v4.10.0 (#11048) ([ipfs/kubo#11048](https://github.com/ipfs/kubo/pull/11048))
|
||||
- fix(provider/stats): number format (#11045) ([ipfs/kubo#11045](https://github.com/ipfs/kubo/pull/11045))
|
||||
- provider: protect libp2p connections (#11028) ([ipfs/kubo#11028](https://github.com/ipfs/kubo/pull/11028))
|
||||
- Merge release v0.38.2 ([ipfs/kubo#11044](https://github.com/ipfs/kubo/pull/11044))
|
||||
- Upgrade to Boxo v0.35.1 (#11043) ([ipfs/kubo#11043](https://github.com/ipfs/kubo/pull/11043))
|
||||
- feat(provider): resume cycle (#11031) ([ipfs/kubo#11031](https://github.com/ipfs/kubo/pull/11031))
|
||||
- chore: upgrade pebble to v2.1.1 (#11040) ([ipfs/kubo#11040](https://github.com/ipfs/kubo/pull/11040))
|
||||
- fix(cli): provide stat cosmetics (#11034) ([ipfs/kubo#11034](https://github.com/ipfs/kubo/pull/11034))
|
||||
- fix: go-libp2p v0.44 with self-healing UPnP port mappings (#11032) ([ipfs/kubo#11032](https://github.com/ipfs/kubo/pull/11032))
|
||||
- feat(provide): slow reprovide alerts when SweepEnabled (#11021) ([ipfs/kubo#11021](https://github.com/ipfs/kubo/pull/11021))
|
||||
- feat: trace delegated routing http client (#11017) ([ipfs/kubo#11017](https://github.com/ipfs/kubo/pull/11017))
|
||||
- feat(provide): detailed `ipfs provide stat` (#11019) ([ipfs/kubo#11019](https://github.com/ipfs/kubo/pull/11019))
|
||||
- config: increase default Provide.DHT.MaxProvideConnsPerWorker (#11016) ([ipfs/kubo#11016](https://github.com/ipfs/kubo/pull/11016))
|
||||
- docs: update release checklist based on v0.38.0 learnings (#11007) ([ipfs/kubo#11007](https://github.com/ipfs/kubo/pull/11007))
|
||||
- chore: merge release v0.38.1 ([ipfs/kubo#11020](https://github.com/ipfs/kubo/pull/11020))
|
||||
- fix: migrations for Windows (#11010) ([ipfs/kubo#11010](https://github.com/ipfs/kubo/pull/11010))
|
||||
- Upgrade go-ds-pebble to v0.5.3 (#11011) ([ipfs/kubo#11011](https://github.com/ipfs/kubo/pull/11011))
|
||||
- Merge release v0.38.0 ([ipfs/kubo#11006](https://github.com/ipfs/kubo/pull/11006))
|
||||
- feat: add docker stub for deprecated ipfs/go-ipfs name (#10998) ([ipfs/kubo#10998](https://github.com/ipfs/kubo/pull/10998))
|
||||
- docs: add sweeping provide worker count recommendation (#11001) ([ipfs/kubo#11001](https://github.com/ipfs/kubo/pull/11001))
|
||||
- chore: bump go-libp2p-kad-dht to v0.35.0 (#11002) ([ipfs/kubo#11002](https://github.com/ipfs/kubo/pull/11002))
|
||||
- upgrade go-ds-pebble to v0.5.2 (#11000) ([ipfs/kubo#11000](https://github.com/ipfs/kubo/pull/11000))
|
||||
- Upgrade to Boxo v0.35.0 (#10999) ([ipfs/kubo#10999](https://github.com/ipfs/kubo/pull/10999))
|
||||
- Non-functional changes (#10996) ([ipfs/kubo#10996](https://github.com/ipfs/kubo/pull/10996))
|
||||
- chore: update boxo and kad-dht dependencies (#10995) ([ipfs/kubo#10995](https://github.com/ipfs/kubo/pull/10995))
|
||||
- fix: update webui to v4.9.1 (#10994) ([ipfs/kubo#10994](https://github.com/ipfs/kubo/pull/10994))
|
||||
- fix: provider merge conflicts (#10989) ([ipfs/kubo#10989](https://github.com/ipfs/kubo/pull/10989))
|
||||
- fix(mfs): add soft limit for `--flush=false` (#10985) ([ipfs/kubo#10985](https://github.com/ipfs/kubo/pull/10985))
|
||||
- fix: provide Filestore nodes (#10990) ([ipfs/kubo#10990](https://github.com/ipfs/kubo/pull/10990))
|
||||
- feat: limit pin names to 255 bytes (#10981) ([ipfs/kubo#10981](https://github.com/ipfs/kubo/pull/10981))
|
||||
- fix: SweepingProvider slow start (#10980) ([ipfs/kubo#10980](https://github.com/ipfs/kubo/pull/10980))
|
||||
- chore: start v0.39.0 release cycle
|
||||
- github.com/gammazero/deque (v1.1.0 -> v1.2.0):
|
||||
- add slice operation functions (#40) ([gammazero/deque#40](https://github.com/gammazero/deque/pull/40))
|
||||
- maintain base capacity after IterPop iteration (#44) ([gammazero/deque#44](https://github.com/gammazero/deque/pull/44))
|
||||
- github.com/ipfs/boxo (v0.35.1 -> v0.35.2):
|
||||
- Release v0.35.2 ([ipfs/boxo#1068](https://github.com/ipfs/boxo/pull/1068))
|
||||
- fix(logs): upgrade go-libp2p to v0.45.0 and go-log to v2.9.0 ([ipfs/boxo#1066](https://github.com/ipfs/boxo/pull/1066))
|
||||
- github.com/ipfs/go-cid (v0.5.0 -> v0.6.0):
|
||||
- v0.6.0 bump (#178) ([ipfs/go-cid#178](https://github.com/ipfs/go-cid/pull/178))
|
||||
- github.com/ipfs/go-ds-pebble (v0.5.3 -> v0.5.7):
|
||||
- new version (#74) ([ipfs/go-ds-pebble#74](https://github.com/ipfs/go-ds-pebble/pull/74))
|
||||
- do not override logger if logger is provided (#72) ([ipfs/go-ds-pebble#72](https://github.com/ipfs/go-ds-pebble/pull/72))
|
||||
- new version (#70) ([ipfs/go-ds-pebble#70](https://github.com/ipfs/go-ds-pebble/pull/70))
|
||||
- new-version (#68) ([ipfs/go-ds-pebble#68](https://github.com/ipfs/go-ds-pebble/pull/68))
|
||||
- Do not allow batch to be reused after commit (#67) ([ipfs/go-ds-pebble#67](https://github.com/ipfs/go-ds-pebble/pull/67))
|
||||
- new version (#66) ([ipfs/go-ds-pebble#66](https://github.com/ipfs/go-ds-pebble/pull/66))
|
||||
- Make pebble write options configurable ([ipfs/go-ds-pebble#63](https://github.com/ipfs/go-ds-pebble/pull/63))
|
||||
- github.com/ipfs/go-dsqueue (v0.1.0 -> v0.1.1):
|
||||
- new version (#26) ([ipfs/go-dsqueue#26](https://github.com/ipfs/go-dsqueue/pull/26))
|
||||
- update deque package and add stress test (#25) ([ipfs/go-dsqueue#25](https://github.com/ipfs/go-dsqueue/pull/25))
|
||||
- github.com/ipfs/go-log/v2 (v2.8.2 -> v2.9.0):
|
||||
- chore: release v2.9.0 (#177) ([ipfs/go-log#177](https://github.com/ipfs/go-log/pull/177))
|
||||
- fix: go-libp2p and slog interop (#176) ([ipfs/go-log#176](https://github.com/ipfs/go-log/pull/176))
|
||||
- github.com/libp2p/go-libp2p (v0.43.0 -> v0.45.0):
|
||||
- Release v0.45.0 (#3424) ([libp2p/go-libp2p#3424](https://github.com/libp2p/go-libp2p/pull/3424))
|
||||
- feat(gologshim): Add SetDefaultHandler (#3418) ([libp2p/go-libp2p#3418](https://github.com/libp2p/go-libp2p/pull/3418))
|
||||
- Update Drips ownedBy address in FUNDING.json
|
||||
- fix(websocket): use debug level for http.Server errors
|
||||
- chore: release v0.44.0
|
||||
- autonatv2: fix normalization for websocket addrs
|
||||
- autonatv2: remove dependency on webrtc and webtransport
|
||||
- quicreuse: update libp2p/go-netroute (#3405) ([libp2p/go-libp2p#3405](https://github.com/libp2p/go-libp2p/pull/3405))
|
||||
- basichost: don't advertise unreachable addrs. (#3357) ([libp2p/go-libp2p#3357](https://github.com/libp2p/go-libp2p/pull/3357))
|
||||
- basichost: improve autonatv2 reachability logic (#3356) ([libp2p/go-libp2p#3356](https://github.com/libp2p/go-libp2p/pull/3356))
|
||||
- basichost: fix lint error
|
||||
- basichost: move EvtLocalAddrsChanged to addrs_manager (#3355) ([libp2p/go-libp2p#3355](https://github.com/libp2p/go-libp2p/pull/3355))
|
||||
- chore: gitignore go.work files
|
||||
- refactor!: move insecure transport outside of core
|
||||
- refactor: drop go-varint dependency
|
||||
- refactor!: move canonicallog package outside of core
|
||||
- fix: assignment to entry in nil map
|
||||
- docs: Update contribute section with mailing list and irc (#3387) ([libp2p/go-libp2p#3387](https://github.com/libp2p/go-libp2p/pull/3387))
|
||||
- README: remove Drand from notable users section
|
||||
- chore: add help comment
|
||||
- refactor: replace context.WithCancel with t.Context
|
||||
- feat(network): Add Conn.As
|
||||
- Skip mdns tests on macOS in CI
|
||||
- fix: deduplicate NAT port mapping requests
|
||||
- fix: heal NAT mappings after router restart
|
||||
- feat: relay: add option for custom filter function
|
||||
- docs: remove broken link (#3375) ([libp2p/go-libp2p#3375](https://github.com/libp2p/go-libp2p/pull/3375))
|
||||
- AI tooling must be disclosed for contributions (#3372) ([libp2p/go-libp2p#3372](https://github.com/libp2p/go-libp2p/pull/3372))
|
||||
- feat: Migrate to log/slog (#3364) ([libp2p/go-libp2p#3364](https://github.com/libp2p/go-libp2p/pull/3364))
|
||||
- basichost: move observed address manager to basichost (#3332) ([libp2p/go-libp2p#3332](https://github.com/libp2p/go-libp2p/pull/3332))
|
||||
- chore: support Go 1.24 & 1.25 (#3366) ([libp2p/go-libp2p#3366](https://github.com/libp2p/go-libp2p/pull/3366))
|
||||
- feat(simlibp2p): Simulated libp2p Networks (#3262) ([libp2p/go-libp2p#3262](https://github.com/libp2p/go-libp2p/pull/3262))
|
||||
- bandwidthcounter: add Reset and TrimIdle methods to reporter interface (#3343) ([libp2p/go-libp2p#3343](https://github.com/libp2p/go-libp2p/pull/3343))
|
||||
- network: rename NAT Types (#3331) ([libp2p/go-libp2p#3331](https://github.com/libp2p/go-libp2p/pull/3331))
|
||||
- refactor(quicreuse): use errors.Join in Close method (#3363) ([libp2p/go-libp2p#3363](https://github.com/libp2p/go-libp2p/pull/3363))
|
||||
- swarm: move AddCertHashes to swarm (#3330) ([libp2p/go-libp2p#3330](https://github.com/libp2p/go-libp2p/pull/3330))
|
||||
- quicreuse: clean up associations for closed listeners. (#3306) ([libp2p/go-libp2p#3306](https://github.com/libp2p/go-libp2p/pull/3306))
|
||||
- github.com/libp2p/go-libp2p-kad-dht (v0.35.1 -> v0.36.0):
|
||||
- new version (#1204) ([libp2p/go-libp2p-kad-dht#1204](https://github.com/libp2p/go-libp2p-kad-dht/pull/1204))
|
||||
- update dependencies (#1205) ([libp2p/go-libp2p-kad-dht#1205](https://github.com/libp2p/go-libp2p-kad-dht/pull/1205))
|
||||
- fix(provider): protect `SweepingProvider.wg` (#1200) ([libp2p/go-libp2p-kad-dht#1200](https://github.com/libp2p/go-libp2p-kad-dht/pull/1200))
|
||||
- fix(ResettableKeystore): race when closing during reset (#1201) ([libp2p/go-libp2p-kad-dht#1201](https://github.com/libp2p/go-libp2p-kad-dht/pull/1201))
|
||||
- fix(provider): conflict resolution (#1199) ([libp2p/go-libp2p-kad-dht#1199](https://github.com/libp2p/go-libp2p-kad-dht/pull/1199))
|
||||
- fix(provider): remove from trie by pruning prefix (#1198) ([libp2p/go-libp2p-kad-dht#1198](https://github.com/libp2p/go-libp2p-kad-dht/pull/1198))
|
||||
- fix(provider): rename metric to follow OpenTelemetry conventions (#1195) ([libp2p/go-libp2p-kad-dht#1195](https://github.com/libp2p/go-libp2p-kad-dht/pull/1195))
|
||||
- fix(provider): resume cycle from persisted keystore (#1193) ([libp2p/go-libp2p-kad-dht#1193](https://github.com/libp2p/go-libp2p-kad-dht/pull/1193))
|
||||
- feat(provider): connectivity callbacks (#1194) ([libp2p/go-libp2p-kad-dht#1194](https://github.com/libp2p/go-libp2p-kad-dht/pull/1194))
|
||||
- feat(provider): trie iterators (#1189) ([libp2p/go-libp2p-kad-dht#1189](https://github.com/libp2p/go-libp2p-kad-dht/pull/1189))
|
||||
- refactor(provider): optimize memory when allocating keys to peers (#1187) ([libp2p/go-libp2p-kad-dht#1187](https://github.com/libp2p/go-libp2p-kad-dht/pull/1187))
|
||||
- refactor(keystore): track size (#1181) ([libp2p/go-libp2p-kad-dht#1181](https://github.com/libp2p/go-libp2p-kad-dht/pull/1181))
|
||||
- Remove go-libp2p-maintainers from codeowners (#1192) ([libp2p/go-libp2p-kad-dht#1192](https://github.com/libp2p/go-libp2p-kad-dht/pull/1192))
|
||||
- switch to bit256.NewKeyFromArray (#1188) ([libp2p/go-libp2p-kad-dht#1188](https://github.com/libp2p/go-libp2p-kad-dht/pull/1188))
|
||||
- fix(provider): `RegionsFromPeers` may return multiple regions (#1185) ([libp2p/go-libp2p-kad-dht#1185](https://github.com/libp2p/go-libp2p-kad-dht/pull/1185))
|
||||
- feat(provider): skip bootstrap reprovide (#1186) ([libp2p/go-libp2p-kad-dht#1186](https://github.com/libp2p/go-libp2p-kad-dht/pull/1186))
|
||||
- refactor(provider): use adaptive deadline for CycleStats cleanup (#1183) ([libp2p/go-libp2p-kad-dht#1183](https://github.com/libp2p/go-libp2p-kad-dht/pull/1183))
|
||||
- refactor(provider/stats): use int64 to avoid overflows (#1182) ([libp2p/go-libp2p-kad-dht#1182](https://github.com/libp2p/go-libp2p-kad-dht/pull/1182))
|
||||
- provider: trigger connectivity check when missing libp2p addresses (#1180) ([libp2p/go-libp2p-kad-dht#1180](https://github.com/libp2p/go-libp2p-kad-dht/pull/1180))
|
||||
- fix(provider): resume cycle (#1176) ([libp2p/go-libp2p-kad-dht#1176](https://github.com/libp2p/go-libp2p-kad-dht/pull/1176))
|
||||
- tests: fix flaky TestProvidesExpire (#1179) ([libp2p/go-libp2p-kad-dht#1179](https://github.com/libp2p/go-libp2p-kad-dht/pull/1179))
|
||||
- tests: fix flaky TestFindPeerWithQueryFilter (#1178) ([libp2p/go-libp2p-kad-dht#1178](https://github.com/libp2p/go-libp2p-kad-dht/pull/1178))
|
||||
- tests: fix #1175 (#1177) ([libp2p/go-libp2p-kad-dht#1177](https://github.com/libp2p/go-libp2p-kad-dht/pull/1177))
|
||||
- feat(provider): exit early region exploration if no new peers discovered (#1174) ([libp2p/go-libp2p-kad-dht#1174](https://github.com/libp2p/go-libp2p-kad-dht/pull/1174))
|
||||
- provider: protect connections (#1172) ([libp2p/go-libp2p-kad-dht#1172](https://github.com/libp2p/go-libp2p-kad-dht/pull/1172))
|
||||
- feat(provider): resume reprovides (#1170) ([libp2p/go-libp2p-kad-dht#1170](https://github.com/libp2p/go-libp2p-kad-dht/pull/1170))
|
||||
- fix(provider): custom logger name (#1173) ([libp2p/go-libp2p-kad-dht#1173](https://github.com/libp2p/go-libp2p-kad-dht/pull/1173))
|
||||
- feat(provider): persist provide queue (#1167) ([libp2p/go-libp2p-kad-dht#1167](https://github.com/libp2p/go-libp2p-kad-dht/pull/1167))
|
||||
- provider: stats (#1144) ([libp2p/go-libp2p-kad-dht#1144](https://github.com/libp2p/go-libp2p-kad-dht/pull/1144))
|
||||
- github.com/probe-lab/go-libdht (v0.3.0 -> v0.4.0):
|
||||
- chore: release v0.4.0 (#26) ([probe-lab/go-libdht#26](https://github.com/probe-lab/go-libdht/pull/26))
|
||||
- feat(key/bit256): memory optimized constructor (#25) ([probe-lab/go-libdht#25](https://github.com/probe-lab/go-libdht/pull/25))
|
||||
- refactor(trie): AddMany memory optimization (#24) ([probe-lab/go-libdht#24](https://github.com/probe-lab/go-libdht/pull/24))
|
||||
|
||||
</details>
|
||||
|
||||
### 👨👩👧👦 Contributors
|
||||
|
||||
| Contributor | Commits | Lines ± | Files Changed |
|
||||
|-------------|---------|---------|---------------|
|
||||
| [@guillaumemichel](https://github.com/guillaumemichel) | 41 | +9906/-1383 | 170 |
|
||||
| [@lidel](https://github.com/lidel) | 30 | +6652/-694 | 97 |
|
||||
| [@sukunrt](https://github.com/sukunrt) | 9 | +1618/-1524 | 39 |
|
||||
| [@MarcoPolo](https://github.com/MarcoPolo) | 17 | +1665/-1452 | 160 |
|
||||
| [@gammazero](https://github.com/gammazero) | 23 | +514/-53 | 29 |
|
||||
| [@Prabhat1308](https://github.com/Prabhat1308) | 1 | +197/-67 | 4 |
|
||||
| [@peterargue](https://github.com/peterargue) | 3 | +82/-25 | 5 |
|
||||
| [@cargoedit](https://github.com/cargoedit) | 1 | +35/-72 | 14 |
|
||||
| [@hsanjuan](https://github.com/hsanjuan) | 2 | +66/-29 | 5 |
|
||||
| [@shoriwe](https://github.com/shoriwe) | 1 | +68/-21 | 3 |
|
||||
| [@dennis-tra](https://github.com/dennis-tra) | 2 | +27/-2 | 2 |
|
||||
| [@Lil-Duckling-22](https://github.com/Lil-Duckling-22) | 1 | +4/-1 | 1 |
|
||||
| [@crStiv](https://github.com/crStiv) | 1 | +1/-3 | 1 |
|
||||
| [@cpeliciari](https://github.com/cpeliciari) | 1 | +3/-0 | 1 |
|
||||
| [@rvagg](https://github.com/rvagg) | 1 | +1/-1 | 1 |
|
||||
| [@p-shahi](https://github.com/p-shahi) | 1 | +1/-1 | 1 |
|
||||
| [@lbarrettanderson](https://github.com/lbarrettanderson) | 1 | +1/-1 | 1 |
|
||||
| [@filipremb](https://github.com/filipremb) | 1 | +1/-1 | 1 |
|
||||
| [@marten-seemann](https://github.com/marten-seemann) | 1 | +0/-1 | 1 |
|
||||
|
||||
@ -2118,6 +2118,7 @@ connections this setting can generate.
|
||||
> users. The system will only use workers as needed - unused resources won't be
|
||||
> consumed. Ensure you adjust the swarm [connection manager](#swarmconnmgr) and
|
||||
> [resource manager](#swarmresourcemgr) configuration accordingly.
|
||||
> See [Capacity Planning](https://github.com/ipfs/kubo/blob/master/docs/provide-stats.md#capacity-planning) for more details.
|
||||
|
||||
Default: `16`
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user