set -eEuo pipefail
WORKSPACE_METADATA="$(cargo metadata --format-version=1 --no-deps)"
function package_dir_for() {
local package_name="$1"
local manifest_path
manifest_path="$(
echo "$WORKSPACE_METADATA" \
| jq -r --arg package_name "$package_name" '.packages[] | select(.name == $package_name) | .manifest_path' \
| head -n 1
)"
if [[ -z "$manifest_path" || "$manifest_path" == "null" ]]; then
echo "Could not determine package directory for $package_name" >&2
return 1
fi
dirname "$manifest_path"
}
function bump_changelog_version() {
local package_dir="$1"
local version="$2"
local changelog_file="${package_dir}/CHANGELOG.md"
local readme_file="${package_dir}/README.md"
local unreleased_line
local next_heading_line
local previous_version
local change_chunk_file
local line_count
if [[ ! -f "$changelog_file" ]]; then
echo "Skipping ${package_dir}: no CHANGELOG.md"
return 0
fi
if awk -v version="$version" '$0 == "## " version { found = 1 } END { exit !found }' "$changelog_file"; then
echo "Skipping ${changelog_file}: already contains ${version}"
return 0
fi
unreleased_line="$(awk '/^## Unreleased$/ { print NR; exit }' "$changelog_file")"
if [[ -z "$unreleased_line" ]]; then
echo "Skipping ${changelog_file}: no '## Unreleased' heading"
return 0
fi
next_heading_line="$(
awk -v start="$unreleased_line" 'NR > start && /^## / { print NR; exit }' "$changelog_file"
)"
if [[ -z "$next_heading_line" ]]; then
echo "Skipping ${changelog_file}: no version headings found after '## Unreleased'"
return 0
fi
previous_version="$(sed -n "${next_heading_line}s/^## //p" "$changelog_file")"
change_chunk_file="$(mktemp)"
line_count="$(wc -l < "$changelog_file" | awk '{ print $1 }')"
echo "${changelog_file} -> ${version}"
sed -n "$((unreleased_line + 1)),$((next_heading_line - 1))p" "$changelog_file" \
| awk '
{
lines[NR] = $0
}
END {
first = 1
while (first <= NR && lines[first] ~ /^[[:space:]]*$/) {
first++
}
last = NR
while (last >= first && lines[last] ~ /^[[:space:]]*$/) {
last--
}
for (i = first; i <= last; i++) {
print lines[i]
}
}
' >"$change_chunk_file"
if [[ "$(wc -w "$change_chunk_file" | awk '{ print $1 }')" == "0" ]]; then
printf '%s\n' "- No significant changes since \`${previous_version}\`." >"$change_chunk_file"
fi
(
sed -n "1,${unreleased_line}p" "$changelog_file"
echo
echo "## $version"
echo
sed -n '1,$p' "$change_chunk_file"
echo
sed -n "${next_heading_line},${line_count}p" "$changelog_file"
) >"$changelog_file.bak"
mv "$changelog_file.bak" "$changelog_file"
rm -f "$change_chunk_file"
if [[ -f "$readme_file" && -n "$previous_version" ]]; then
sed -i.bak -E "s#([=/])${previous_version}([/)])#\\1${version}\\2#g" "$readme_file"
rm -f "${readme_file}.bak"
fi
}
RELEASE_PLZ_PR_JSON="$1"
PR_NUMBER="$(echo "$RELEASE_PLZ_PR_JSON" | jq -r '.number')"
if [[ -n "$PR_NUMBER" && "$PR_NUMBER" != "null" ]]; then
gh pr checkout "$PR_NUMBER"
WORKSPACE_METADATA="$(cargo metadata --format-version=1 --no-deps)"
fi
specs="$(echo "$RELEASE_PLZ_PR_JSON" | jq -r '.releases[] | "\(.package_name):\(.version)"')"
for spec in $specs; do
name="$(echo "$spec" | cut -d: -f1)"
version="$(echo "$spec" | cut -d: -f2)"
package_dir="$(package_dir_for "$name")"
bump_changelog_version "$package_dir" "$version"
done
if [[ -n "$PR_NUMBER" && "$PR_NUMBER" != "null" ]]; then
git add --all
if ! git diff --cached --quiet; then
git commit -m "docs: update changelog versions"
git push
fi
fi