diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 3ab351bf..2690be10 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -20,6 +20,19 @@ reviews: - "!deps/**" - "!.scratch/**" + pre_merge_checks: + custom_checks: + - name: "Changelog entry" + mode: warning + instructions: | + CONTRIBUTING.md#changelog defines which changes are user-visible. + Pass if the PR makes no user-visible change. + Pass if the PR adds an entry to the Unreleased section of CHANGELOG.md + describing its user-visible change. + Pass if the PR only edits CHANGELOG.md, such as cutting a release. + Fail if the PR makes a user-visible change and adds no such entry. + Name the change that needs an entry and suggest the line. + path_instructions: - path: "**" instructions: | @@ -36,6 +49,8 @@ reviews: - BUILD.md — CMake presets, moxygen pinning, CPM-fetched deps. - RUNNING.md — CLI flags and running a relay. - CONTRIBUTING.md — PR scope, review, branch and merge conventions. + - CHANGELOG.md — user-visible changes per release; entry rules in + CONTRIBUTING.md#changelog. - docs/config.md — full YAML configuration reference. - docs/logging.md — the --logging flag and XLOG conventions. - docs/metrics.md — Prometheus endpoint and metric names. @@ -159,6 +174,12 @@ reviews: docs/release.md describes the release branch model. PR CI runs without secrets; publish, release and deploy run only on push to main. + - path: "CHANGELOG.md" + instructions: | + New entries go in the Unreleased section; a released section changes + only when a release is cut or to fix an error in it. Check each new + line against CONTRIBUTING.md#changelog. + - path: "docs/ref/**" instructions: | Vendored IETF draft text. This is normative reference material, not diff --git a/.github/workflows/version-release.yml b/.github/workflows/version-release.yml index 6275a2e2..e4d94d48 100644 --- a/.github/workflows/version-release.yml +++ b/.github/workflows/version-release.yml @@ -35,6 +35,9 @@ name: version release # One dispatch releases both repos, tags # agreeing by construction. # +# Release notes open with the [] section of CHANGELOG.md at the +# snapshot commit; validate fails when a non-prerelease version has none. +# # Snapshot source — derived from dispatched ref: # dispatched on main → consume snapshot-latest # dispatched on release/vM.m → consume snapshot-vM.m-latest @@ -79,6 +82,7 @@ jobs: snapshot_sha: ${{ steps.v.outputs.snapshot_sha }} moxygen_ref: ${{ steps.v.outputs.moxygen_ref }} has_portable: ${{ steps.v.outputs.has_portable }} + changelog: ${{ steps.v.outputs.changelog }} steps: - uses: actions/checkout@v5 with: @@ -134,6 +138,21 @@ jobs: exit 1 fi + # Release notes open with the CHANGELOG.md section as of the commit + # being tagged. A prerelease may go without one. + CHANGELOG_SRC=$(mktemp) + git show "$SNAPSHOT_SHA:CHANGELOG.md" > "$CHANGELOG_SRC" 2>/dev/null || true + if ! CHANGELOG=$(scripts/dev/changelog-section.sh "$VERSION" "$CHANGELOG_SRC"); then + if [[ "$VERSION" != *-* ]]; then + echo "Error: CHANGELOG.md at ${SNAPSHOT_SHA:0:12} has no [$VERSION] section." >&2 + echo "Land the release's changelog PR (docs/release.md#changelog) and wait for $SNAPSHOT_TAG to rebuild." >&2 + exit 1 + fi + CHANGELOG="" + fi + # Root-relative links resolve against the tagged tree. + CHANGELOG=$(sed -E "s#\]\(/#](${{ github.server_url }}/${{ github.repository }}/blob/${TAG}/#g" <<<"$CHANGELOG") + # Resolve the moxygen tag exactly the way the build will (git tags # at the pin; immutable v* preferred over snapshot-*). Anything else # (moxygen's newest release, say) disagrees with MOXYGEN_REV, fails @@ -214,6 +233,9 @@ jobs: echo "==> moxygen $MOX_REF lacks portable assets — portable matrix will be skipped" fi + # Random delimiter: a fixed one could appear in the changelog text, + # end the value early, and let the lines after it override outputs. + DELIM="CHANGELOG_$(openssl rand -hex 16)" { echo "version=$VERSION" echo "tag=$TAG" @@ -221,6 +243,9 @@ jobs: echo "snapshot_sha=$SNAPSHOT_SHA" echo "moxygen_ref=$MOX_REF" echo "has_portable=$HAS_PORTABLE" + echo "changelog<<$DELIM" + printf '%s\n' "$CHANGELOG" + echo "$DELIM" } >> "$GITHUB_OUTPUT" # ════════════════════════════════════════════════════════════════════════════ @@ -249,6 +274,7 @@ jobs: HAS_PORTABLE: ${{ needs.validate.outputs.has_portable }} SNAPSHOT_TAG: ${{ needs.validate.outputs.snapshot_tag }} SNAPSHOT_SHA: ${{ needs.validate.outputs.snapshot_sha }} + CHANGELOG: ${{ needs.validate.outputs.changelog }} run: | if [ "$HAS_PORTABLE" = "true" ]; then PORTABLE_NOTE="**Portable tarballs** built against moxygen \`${MOX_REF}\`: @@ -285,6 +311,8 @@ jobs: --title "moqx $VERSION" \ "${PRERELEASE_FLAG[@]}" \ --notes "$(cat < + + + +All notable changes to moqx are recorded here. +The format follows [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/), and versions follow [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). +How to add an entry: see [CONTRIBUTING.md](/CONTRIBUTING.md#changelog). + +[Unreleased] +============ + +- **Breaking:** dropped MoQT draft-14 support. ([#761](https://github.com/openmoq/moqx/pull/761)) + - A config with [`moqt_versions`](/docs/config.md#listeners) containing 14 fails at startup. + +## Added + +- Draft-18 SUBSCRIBE rendezvous timeout. ([#549](https://github.com/openmoq/moqx/pull/549), [#652](https://github.com/openmoq/moqx/pull/652), [#728](https://github.com/openmoq/moqx/pull/728)) +- The picoquic listener uses all I/O threads. ([#721](https://github.com/openmoq/moqx/pull/721)) +- Docker image: congestion control (`MOQX_CC`, `MOQX_PICO_CC`, `MOQX_BBR_SKIP_PROBE_RTT`) and qlog sampling (`MOQX_QLOG_SAMPLE`, `MOQX_QLOG_DIR`). ([#778](https://github.com/openmoq/moqx/pull/778)) + +## Changed + +- A draft-18 SUBSCRIBE_NAMESPACE or SUBSCRIBE_TRACKS matching more than 1000 namespaces and tracks fails with NAMESPACE_TOO_LARGE. ([#667](https://github.com/openmoq/moqx/pull/667)) + +## Fixed + +- A thread could spin at 100% CPU during cache eviction. ([#720](https://github.com/openmoq/moqx/pull/720)) +- A large object re-delivered in chunks tore down the subscription. ([#699](https://github.com/openmoq/moqx/pull/699)) +- With `use_local_forwarders`, a track could lose its upstream subscription. ([#722](https://github.com/openmoq/moqx/pull/722)) +- With `use_local_forwarders`, concurrent SUBSCRIBEs for one track could fail. ([#723](https://github.com/openmoq/moqx/pull/723)) +- The relay requested objects from upstream with no forwarding subscriber. ([#742](https://github.com/openmoq/moqx/pull/742)) +- The relay stopped reconnecting after an upstream dropped mid-handshake. ([#737](https://github.com/openmoq/moqx/pull/737)) +- FETCH served from the cache could return wrong or missing objects. ([#734](https://github.com/openmoq/moqx/pull/734), [#735](https://github.com/openmoq/moqx/pull/735), [#736](https://github.com/openmoq/moqx/pull/736), [#750](https://github.com/openmoq/moqx/pull/750), [#755](https://github.com/openmoq/moqx/pull/755)) +- A crash in multi-threaded mode. ([#733](https://github.com/openmoq/moqx/pull/733)) +- A shutdown error log for relays with an upstream. ([#746](https://github.com/openmoq/moqx/pull/746)) +- A peer's namespace subscription outlived its session. ([#775](https://github.com/openmoq/moqx/pull/775)) +- An upstream connect failure is logged only once. ([#744](https://github.com/openmoq/moqx/pull/744)) +- With `use_local_forwarders`, a joining FETCH pipelined behind its SUBSCRIBE resolved against a stale or missing Largest. ([#783](https://github.com/openmoq/moqx/pull/783)) + +[0.3.5] - 2026-09-11 +==================== + +## Dependencies + +- moxygen [v0.3.5](https://github.com/openmoq/moxygen/releases/tag/v0.3.5) + +[0.3.4] - 2026-09-05 +==================== + +- [Per-track QoS metrics](/docs/metrics.md#per-track-metrics) and dashboards. ([#539](https://github.com/openmoq/moqx/pull/539), [#640](https://github.com/openmoq/moqx/pull/640)) +- `/state` is streamed and reports correct per-track counts. ([#627](https://github.com/openmoq/moqx/pull/627), [#630](https://github.com/openmoq/moqx/pull/630), [#632](https://github.com/openmoq/moqx/pull/632), [#633](https://github.com/openmoq/moqx/pull/633)) + +## Changed + +- FETCH validates its requested range. ([#662](https://github.com/openmoq/moqx/pull/662)) + +## Fixed + +- Crashes in multi-threaded mode. ([#653](https://github.com/openmoq/moqx/pull/653), [#654](https://github.com/openmoq/moqx/pull/654), [#677](https://github.com/openmoq/moqx/pull/677), [#683](https://github.com/openmoq/moqx/pull/683)) +- FETCH served from the cache reported the wrong End Location. ([#678](https://github.com/openmoq/moqx/pull/678), [#679](https://github.com/openmoq/moqx/pull/679)) +- The datagram `lastInGroup` flag was dropped. ([#681](https://github.com/openmoq/moqx/pull/681)) +- SUBSCRIBE and FETCH failed past namespace nodes with no publisher. ([#684](https://github.com/openmoq/moqx/pull/684)) +- FETCH preferred a namespace publisher over an exact-track upstream. ([#685](https://github.com/openmoq/moqx/pull/685)) +- Draft-18 rejected empty namespaces. ([#687](https://github.com/openmoq/moqx/pull/687)) + +## Dependencies + +- moxygen [v0.3.4](https://github.com/openmoq/moxygen/releases/tag/v0.3.4) + +[0.3.1] - 2026-08-23 +==================== + +## Fixed + +- The release container image reports the release version. ([#637](https://github.com/openmoq/moqx/pull/637)) + +[0.3.0] - 2026-08-23 +==================== + +- [Relay hops](/docs/relay-hops.md): namespace loops across relays are dropped. ([#502](https://github.com/openmoq/moqx/pull/502)) +- [Per-track counters](/docs/metrics.md#per-track-metrics) at `/metrics/track`. ([#532](https://github.com/openmoq/moqx/pull/532), [#533](https://github.com/openmoq/moqx/pull/533), [#561](https://github.com/openmoq/moqx/pull/561)) +- [Anonymous auth claims](/docs/config.md#anonymous-claim). ([#553](https://github.com/openmoq/moqx/pull/553)) +- `/logs` admin endpoint. ([#491](https://github.com/openmoq/moqx/pull/491)) + +## Added + +- [`/info`](/RUNNING.md#health-check) reports start time and uptime. ([#572](https://github.com/openmoq/moqx/pull/572)) +- [`omit_metadata`](/docs/metrics.md#omitting-metadata) on the metrics endpoint. ([#604](https://github.com/openmoq/moqx/pull/604)) +- Multiple AUTHORIZATION_TOKEN parameters per message. ([#552](https://github.com/openmoq/moqx/pull/552)) +- Version reporting in the published artifacts. ([#505](https://github.com/openmoq/moqx/pull/505)) + +## Changed + +- PUBLISH counters are named by relay role. ([#528](https://github.com/openmoq/moqx/pull/528)) + +## Fixed + +- With `use_local_forwarders`, subscribers were accepted before the upstream answered. ([#545](https://github.com/openmoq/moqx/pull/545)) +- With `use_local_forwarders`, a track's subscribers could split across forwarders. ([#546](https://github.com/openmoq/moqx/pull/546)) +- A crash at shutdown. ([#587](https://github.com/openmoq/moqx/pull/587)) +- The runtime Docker images lacked libevent. ([#598](https://github.com/openmoq/moqx/pull/598)) + +## Dependencies + +- moxygen [v0.3.0](https://github.com/openmoq/moxygen/releases/tag/v0.3.0) + +[0.2.1] - 2026-07-23 +==================== + +There is no 0.2.0 release; this is the first release with these changes. + +- Multi-threaded relay with [`threads`](/docs/config.md#top-level-structure). ([#361](https://github.com/openmoq/moqx/pull/361), [#362](https://github.com/openmoq/moqx/pull/362), [#364](https://github.com/openmoq/moqx/pull/364), [#365](https://github.com/openmoq/moqx/pull/365)) +- Draft-18 SUBSCRIBE_TRACKS. ([#411](https://github.com/openmoq/moqx/pull/411)) +- proxygen [qmux listener](/docs/config.md#listeners). ([#420](https://github.com/openmoq/moqx/pull/420)) +- [CAT token authorization](/docs/config.md#authentication-and-authorization). ([#264](https://github.com/openmoq/moqx/pull/264), [#286](https://github.com/openmoq/moqx/pull/286), [#468](https://github.com/openmoq/moqx/pull/468)) + +## Added + +- PKCS#12 TLS bundles. ([#460](https://github.com/openmoq/moqx/pull/460)) +- [`GET /config`](/docs/config.md#endpoints) admin endpoint. ([#453](https://github.com/openmoq/moqx/pull/453)) +- [`--logging` and `--log-handler`](/docs/logging.md) flags. ([#437](https://github.com/openmoq/moqx/pull/437)) +- [qlog](/docs/logging.md#qlog-separately-for-structured-quic-analysis) for mvfst. ([#464](https://github.com/openmoq/moqx/pull/464)) +- [mlog](/docs/config.md#loggingmlog) structured logging. ([#306](https://github.com/openmoq/moqx/pull/306)) +- More listener options. ([#301](https://github.com/openmoq/moqx/pull/301), [#374](https://github.com/openmoq/moqx/pull/374), [#421](https://github.com/openmoq/moqx/pull/421)) +- [QUIC transport metrics](/docs/metrics.md). ([#283](https://github.com/openmoq/moqx/pull/283), [#294](https://github.com/openmoq/moqx/pull/294), [#295](https://github.com/openmoq/moqx/pull/295)) +- Subgroup-reset and object-ack-latency metrics. ([#462](https://github.com/openmoq/moqx/pull/462), [#478](https://github.com/openmoq/moqx/pull/478)) +- Docker image: `MOQX_ENDPOINT` and a config template. ([#319](https://github.com/openmoq/moqx/pull/319), [#428](https://github.com/openmoq/moqx/pull/428)) + +## Changed + +- The published image uses jemalloc and ships a stats stack. ([#480](https://github.com/openmoq/moqx/pull/480)) +- A [max cache duration](/docs/config.md#cache) of 0 disables caching. ([#302](https://github.com/openmoq/moqx/pull/302)) +- Default `moqt_versions` is 14 and 16; draft 18 is opt-in. ([#405](https://github.com/openmoq/moqx/pull/405)) +- Bidirectional NAMESPACE forwarding requires draft 16+. ([#406](https://github.com/openmoq/moqx/pull/406)) +- Faster UDP receive on mvfst. ([#337](https://github.com/openmoq/moqx/pull/337), [#350](https://github.com/openmoq/moqx/pull/350), [#371](https://github.com/openmoq/moqx/pull/371)) +- [Log categories](/docs/logging.md#the-category-hierarchy) are rooted under `moqx.*`. ([#370](https://github.com/openmoq/moqx/pull/370)) +- The datagram send queue is deeper and drops oldest-first. ([#450](https://github.com/openmoq/moqx/pull/450)) + +## Fixed + +- The `quicActiveStreams` metric could go negative. ([#256](https://github.com/openmoq/moqx/pull/256)) +- Crashes in the cache and in stats collection. ([#303](https://github.com/openmoq/moqx/pull/303), [#325](https://github.com/openmoq/moqx/pull/325)) +- A memory leak in stats collection. ([#423](https://github.com/openmoq/moqx/pull/423)) +- Shutdown could hang. ([#359](https://github.com/openmoq/moqx/pull/359)) +- An unreadable TLS certificate aborted the relay. ([#434](https://github.com/openmoq/moqx/pull/434)) +- A bad bind address gave no clean error. ([#461](https://github.com/openmoq/moqx/pull/461)) +- With `use_local_forwarders`, races in track status, fetch and eviction. ([#443](https://github.com/openmoq/moqx/pull/443), [#445](https://github.com/openmoq/moqx/pull/445), [#451](https://github.com/openmoq/moqx/pull/451), [#452](https://github.com/openmoq/moqx/pull/452)) + +## Dependencies + +- moxygen [v0.2.0](https://github.com/openmoq/moxygen/releases/tag/v0.2.0) +- catapult [2bbf479](https://github.com/Quicr/catapult/commit/2bbf479fe2e65e425624316d335443a8c0fc0507) + +[0.1.4] - 2026-05-04 +==================== + +The first tagged release. + +- The relay, forked from moxygen's MoQRelay. ([#16](https://github.com/openmoq/moqx/pull/16)) +- [Multi-service routing](/docs/config.md#services) by authority and path. ([#58](https://github.com/openmoq/moqx/pull/58)) +- [Relay peering](/docs/config.md#upstreams) through per-service upstreams. ([#80](https://github.com/openmoq/moqx/pull/80)) +- [Multiple listeners](/docs/config.md#listeners), each on mvfst or picoquic. ([#109](https://github.com/openmoq/moqx/pull/109), [#111](https://github.com/openmoq/moqx/pull/111), [#119](https://github.com/openmoq/moqx/pull/119), [#135](https://github.com/openmoq/moqx/pull/135)) +- TRACK_FILTER top-N track selection. ([#160](https://github.com/openmoq/moqx/pull/160), [#161](https://github.com/openmoq/moqx/pull/161), [#162](https://github.com/openmoq/moqx/pull/162), [#164](https://github.com/openmoq/moqx/pull/164), [#165](https://github.com/openmoq/moqx/pull/165), [#166](https://github.com/openmoq/moqx/pull/166), [#169](https://github.com/openmoq/moqx/pull/169)) +- [HTTP admin API](/docs/config.md#admin-server). ([#34](https://github.com/openmoq/moqx/pull/34), [#46](https://github.com/openmoq/moqx/pull/46), [#118](https://github.com/openmoq/moqx/pull/118), [#146](https://github.com/openmoq/moqx/pull/146), [#220](https://github.com/openmoq/moqx/pull/220)) + +## Added + +- [YAML config](/docs/config.md). +- [QUIC transport settings](/docs/config.md#quic-settings) per listener. ([#113](https://github.com/openmoq/moqx/pull/113), [#131](https://github.com/openmoq/moqx/pull/131)) +- Upstream NEW_GROUP_REQUEST forwarding. ([#149](https://github.com/openmoq/moqx/pull/149)) +- [Cache config](/docs/config.md#cache). ([#140](https://github.com/openmoq/moqx/pull/140)) +- [Prometheus metrics](/docs/metrics.md). ([#49](https://github.com/openmoq/moqx/pull/49), [#93](https://github.com/openmoq/moqx/pull/93), [#130](https://github.com/openmoq/moqx/pull/130), [#137](https://github.com/openmoq/moqx/pull/137)) +- Graceful shutdown on SIGTERM and SIGINT. ([#34](https://github.com/openmoq/moqx/pull/34), [#112](https://github.com/openmoq/moqx/pull/112)) +- Docker images on GHCR, and a rolling snapshot release. ([#38](https://github.com/openmoq/moqx/pull/38), [#40](https://github.com/openmoq/moqx/pull/40)) + +## Dependencies + +- moxygen [v0.1.4](https://github.com/openmoq/moxygen/releases/tag/v0.1.4) +- yaml-cpp [0.8.0](https://github.com/jbeder/yaml-cpp/releases/tag/0.8.0) +- reflect-cpp [v0.18.0](https://github.com/getml/reflect-cpp/releases/tag/v0.18.0) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b4e67239..312ff2bb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,6 +72,23 @@ PR description if preserving history on `main` is warranted. > **Note:** *Delete branch on merge* is the current default setting. +## Changelog + +[CHANGELOG.md](CHANGELOG.md) follows [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/). Versions follow [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). + +- A PR adds its user-visible changes to the `[Unreleased]` section, in the same PR. +- An entry covers what an operator or client of the shipped product can observe. +- A headline feature goes directly under the `[Unreleased]` heading, above the subsections. +- Everything else goes under the matching subheading: `Added`, `Changed`, `Deprecated`, `Removed`, `Fixed` or `Security`. Create the subheading if it is missing. +- Write for the operator, not the reviewer: what changed for them, in one sentence. Name the config key, flag or endpoint. +- Link the doc section that covers the change, when one exists. +- A breaking change starts with `**Breaking:**`. +- Keep the file's style, including: + - version headings in setext form, underlined with `===`; + - full PR links: `([#123](https://github.com/openmoq/moqx/pull/123))`. + +Cutting a release: see [docs/release.md](docs/release.md#changelog). + ## Local development Before submitting: diff --git a/docs/ci-architecture.md b/docs/ci-architecture.md index e291eba5..98a6f2bc 100644 --- a/docs/ci-architecture.md +++ b/docs/ci-architecture.md @@ -130,6 +130,7 @@ Merges the sync PR if CI passed. Deletes the sync branch after merge. **Trigger:** manual (version input) | **Time:** <1 min Promotes `snapshot-latest` artifacts to a versioned `vX.Y.Z` release (no rebuild). +Release notes open with the version's [CHANGELOG.md](/CHANGELOG.md) section; see [release.md](/docs/release.md#changelog). --- diff --git a/docs/release.md b/docs/release.md index 8e8b0e46..17347116 100644 --- a/docs/release.md +++ b/docs/release.md @@ -130,6 +130,18 @@ When a release branch needs to absorb fixes from `main`: > TODO (Alan): formal version tagging policy. Today, snapshot releases are the only published artifact. A tagged `vX.Y.Z` release flow (analogous to moxygen's `version release` workflow) is planned — see [issue TBD]. +### Changelog + +Before tagging `vX.Y.Z`, land a PR on the branch being released that updates [CHANGELOG.md](/CHANGELOG.md): + +1. Rename the `[Unreleased]` heading to `[X.Y.Z] - YYYY-MM-DD`, dated the day of the tag. +2. Add a fresh, empty `[Unreleased]` section above it. +3. Review and polish the new release section, especially the headline entries. +4. Append the output of [`scripts/dev/changelog-deps.sh`](/scripts/dev/changelog-deps.sh), which lists the dependencies changed since the previous release. + +[`version release`](/.github/workflows/version-release.yml) opens the GitHub release notes with this section, read at the snapshot commit it tags. +It fails when a non-prerelease version has no section, so dispatch it once the snapshot includes the changelog PR. + ## Deploy `main` auto-deploys to `moqx-main.ci.openmoq.org` after every successful `ci main` run. diff --git a/scripts/dev/changelog-deps.sh b/scripts/dev/changelog-deps.sh new file mode 100755 index 00000000..f4651f2f --- /dev/null +++ b/scripts/dev/changelog-deps.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# changelog-deps.sh — print the `## Dependencies` block for a CHANGELOG.md release +# section: the pins in cmake/dependencies.cmake that changed since the previous release. +# +# Usage: scripts/dev/changelog-deps.sh [] +# +# the release to compare against. Default: the latest v* tag +# reachable from HEAD. +# +# - Run it on the commit being released; see docs/release.md#changelog. +# - Prints nothing when no pin changed; the release then gets no Dependencies section. +# - A pin absent at counts as changed. +# - moxygen is named by the v* release cmake/print-release-tag.cmake resolves +# MOXYGEN_REV to, else by short sha. Resolving needs network access to github.com. +set -euo pipefail +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "$ROOT" + +prev="${1:-$(git describe --tags --abbrev=0 --match 'v*' HEAD)}" +if ! git cat-file -e "$prev:cmake/dependencies.cmake" 2>/dev/null; then + echo "error: $prev has no cmake/dependencies.cmake to compare against" >&2 + exit 1 +fi + +# print-pin.cmake includes dependencies.cmake from its own directory, so the +# previous tag's pins are read from a copy of both files. +prev_dir=$(mktemp -d) +trap 'rm -rf "$prev_dir"' EXIT +git show "$prev:cmake/dependencies.cmake" > "$prev_dir/dependencies.cmake" +cp cmake/print-pin.cmake "$prev_dir/" + +pin() { cmake -DPIN="$1" -P cmake/print-pin.cmake; } +prev_pin() { cmake -DPIN="$1" -P "$prev_dir/print-pin.cmake" 2>/dev/null || true; } +changed() { [[ "$(pin "$1")" != "$(prev_pin "$1")" ]]; } + +lines=() + +if changed MOXYGEN_REV; then + repo=$(pin MOXYGEN_REPOSITORY) + rev=$(pin MOXYGEN_REV) + tag=$(cmake -P cmake/print-release-tag.cmake 2>/dev/null || true) + if [[ "$tag" == v* ]]; then + lines+=("- moxygen [$tag](https://github.com/$repo/releases/tag/$tag)") + else + lines+=("- moxygen [${rev:0:7}](https://github.com/$repo/commit/$rev)") + fi +fi +if changed CATAPULT_REV; then + repo=$(pin CATAPULT_REPOSITORY) + rev=$(pin CATAPULT_REV) + lines+=("- catapult [${rev:0:7}](https://github.com/$repo/commit/$rev)") +fi +if changed YAMLCPP_VERSION; then + v=$(pin YAMLCPP_VERSION) + lines+=("- yaml-cpp [$v](https://github.com/jbeder/yaml-cpp/releases/tag/$v)") +fi +if changed REFLECTCPP_VERSION; then + v=$(pin REFLECTCPP_VERSION) + lines+=("- reflect-cpp [$v](https://github.com/getml/reflect-cpp/releases/tag/$v)") +fi + +((${#lines[@]})) || exit 0 +echo "## Dependencies" +echo +printf '%s\n' "${lines[@]}" diff --git a/scripts/dev/changelog-section.sh b/scripts/dev/changelog-section.sh new file mode 100755 index 00000000..ae3e22bf --- /dev/null +++ b/scripts/dev/changelog-section.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# changelog-section.sh — print the body of one release section of CHANGELOG.md. +# +# Usage: scripts/dev/changelog-section.sh [] +# +# e.g. 1.2.3, matching the `[1.2.3] - YYYY-MM-DD` heading. +# default: CHANGELOG.md at the repository root. +# +# - Prints the lines between that heading and the next release heading, with +# surrounding blank lines trimmed. +# - Exits 1 when the file has no section for . +# - Expects setext version headings; see CONTRIBUTING.md#changelog. +set -euo pipefail +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" + +version="${1:?usage: changelog-section.sh []}" +file="${2:-$ROOT/CHANGELOG.md}" + +awk -v want="[$version]" ' + { line[NR] = $0 } + END { + # A release heading is a line starting "[" whose next line is all "=". + for (i = 1; i < NR; i++) { + if (line[i + 1] !~ /^=+$/ || substr(line[i], 1, 1) != "[") continue + if (start) { stop = i; break } + if (index(line[i], want) == 1) start = i + 2 + } + if (!start) exit 1 + if (!stop) stop = NR + 1 + while (start < stop && line[start] ~ /^[[:space:]]*$/) start++ + while (stop > start && line[stop - 1] ~ /^[[:space:]]*$/) stop-- + for (i = start; i < stop; i++) print line[i] + } +' "$file"