From f56ea077dba0b6581b2fa7c83fc2e027dedfece5 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 17 Jul 2026 09:49:08 -0700 Subject: [PATCH 1/2] prepare 1.7.0-RC2 --- CHANGELOG.md | 2 +- Cargo.lock | 10 +-- RELEASE.md | 54 ++++++++++++++ bump-version.sh | 71 +++++++++++++++++++ conformance/pom.xml | 2 +- dnp3/Cargo.toml | 2 +- dnp3/codegen/pom.xml | 2 +- ffi/bindings/c/CMakeLists.txt | 2 +- .../dotnet/examples/master/Master.csproj | 2 +- .../examples/outstation/Outstation.csproj | 2 +- ffi/bindings/java/examples/pom.xml | 4 +- ffi/bindings/java/pom.xml | 2 +- ffi/dnp3-bindings/Cargo.toml | 2 +- ffi/dnp3-ffi-java/Cargo.toml | 2 +- ffi/dnp3-ffi/Cargo.toml | 2 +- ffi/dnp3-schema/Cargo.toml | 2 +- guide/sitedata.json | 2 +- 17 files changed, 145 insertions(+), 20 deletions(-) create mode 100644 RELEASE.md create mode 100755 bump-version.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 50adec7b..b21edd4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ### 1.7.0-RC2 ### * :star: Add `Database::discard_unselected_events()` to drop undelivered events of selected classes on demand, e.g. from a disconnect handler. Returns per-class discard counts. Opt-in and lossy by design. See [#427](https://github.com/stepfunc/dnp3/issues/427). -* :shield: Update `rustls-webpki` to 0.103.12 to resolve [RUSTSEC-2026-0098](https://rustsec.org/advisories/RUSTSEC-2026-0098) and [RUSTSEC-2026-0099](https://rustsec.org/advisories/RUSTSEC-2026-0099), both concerning incorrect acceptance of X.509 name constraints. Exposure is limited to TLS configurations using `CertificateMode::AuthorityBased`; `SelfSigned` mode bypasses the affected code path. +* :shield: Update `rustls-webpki` to 0.103.13 to resolve [RUSTSEC-2026-0098](https://rustsec.org/advisories/RUSTSEC-2026-0098) and [RUSTSEC-2026-0099](https://rustsec.org/advisories/RUSTSEC-2026-0099), both concerning incorrect acceptance of X.509 name constraints. Exposure is limited to TLS configurations using `CertificateMode::AuthorityBased`; `SelfSigned` mode bypasses the affected code path. * :bell: **This update only affects the prebuilt binary distributions of the bindings (C/C++, .NET, Java).** Rust consumers of the `dnp3` crate pick up the patched `rustls-webpki` automatically on rebuild. ### 1.7.0-RC1 ### diff --git a/Cargo.lock b/Cargo.lock index 79fffc1a..dbbce8e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -391,7 +391,7 @@ dependencies = [ [[package]] name = "dnp3" -version = "1.7.0-RC1" +version = "1.7.0-RC2" dependencies = [ "assert_matches", "chrono", @@ -409,7 +409,7 @@ dependencies = [ [[package]] name = "dnp3-bindings" -version = "1.7.0-RC1" +version = "1.7.0-RC2" dependencies = [ "dnp3-schema", "oo-bindgen", @@ -428,7 +428,7 @@ dependencies = [ [[package]] name = "dnp3-ffi" -version = "1.7.0-RC1" +version = "1.7.0-RC2" dependencies = [ "dnp3", "dnp3-schema", @@ -446,7 +446,7 @@ dependencies = [ [[package]] name = "dnp3-ffi-java" -version = "1.7.0-RC1" +version = "1.7.0-RC2" dependencies = [ "dnp3-ffi", "dnp3-schema", @@ -456,7 +456,7 @@ dependencies = [ [[package]] name = "dnp3-schema" -version = "1.7.0-RC1" +version = "1.7.0-RC2" dependencies = [ "oo-bindgen", "sfio-tokio-ffi", diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 00000000..b14ed8da --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,54 @@ +# Release Process + +Publishing is handled by `.github/workflows/ci.yml`: **pushing a tag `X.Y.Z` +(or `X.Y.Z-RCn`) to a commit on `main` publishes that version** to crates.io, +Maven Central, NuGet, and the docs site, and opens a draft GitHub release. This +file covers only the human steps around that trigger. + +## 1. Prepare a `prepare X.Y.Z` PR against `main` + +Bump the version and refresh `Cargo.lock`: + +```bash +./bump-version.sh X.Y.Z +``` + +The script rewrites the version in every file that hard-codes it (Cargo +manifests, the poms, the .csproj examples, the C `CMakeLists.txt`, and +`guide/sitedata.json`), updates `Cargo.lock`, and verifies nothing was missed. +The file list lives in the script — keep it there, not duplicated here. + +Then update `CHANGELOG.md` (see conventions below). If any dependency versions +changed, refresh `allowed.json` so the packaging license check passes, and +verify any dependency/security claims in the changelog against the actual +`Cargo.lock` versions. + +Open the PR and merge it to `main`. + +## 2. Tag on `main` and push + +CI only publishes from tags, and by convention tags live on `main`: + +```bash +git checkout main && git pull +git tag X.Y.Z && git push origin X.Y.Z +``` + +crates.io publishing is **irreversible** — a version can never be re-published. +Confirm the version before pushing. (`-RCn` publishes as a pre-release, which +cargo won't select by default.) + +## 3. After CI completes + +Review and publish the **draft** GitHub release CI created. The publishers are +idempotent, so re-running the tag's workflow safely retries any that failed. + +## CHANGELOG conventions + +- Each release candidate gets its own `### X.Y.Z-RCn ###` section while the + pre-release cycle is ongoing, so adopters can see the delta between RCs. +- **When cutting the final `X.Y.Z`, collapse all `X.Y.Z-RCn` sections into a + single `### X.Y.Z ###` section** — merge and de-duplicate the bullets and drop + the per-RC headers. The final release gets one coherent entry. +- Bullet prefixes in use: `:star:` feature, `:shield:` security, `:wrench:` + tooling/CI, `:book:` docs. Reference the PR/issue number. diff --git a/bump-version.sh b/bump-version.sh new file mode 100755 index 00000000..d0e0d374 --- /dev/null +++ b/bump-version.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +# +# Bump the crate version across every file that hard-codes it, then refresh +# Cargo.lock. The current version is read from dnp3/Cargo.toml, so you only +# pass the new one. +# +# ./bump-version.sh 1.7.0-RC2 +# +set -euo pipefail + +if [ $# -ne 1 ]; then + echo "usage: $0 (e.g. 1.7.0-RC2)" >&2 + exit 1 +fi + +NEW="$1" +cd "$(dirname "$0")" + +# The files that hard-code the version. This list is the source of truth. +FILES=( + dnp3/Cargo.toml + ffi/dnp3-ffi/Cargo.toml + ffi/dnp3-ffi-java/Cargo.toml + ffi/dnp3-schema/Cargo.toml + ffi/dnp3-bindings/Cargo.toml + dnp3/codegen/pom.xml + conformance/pom.xml + ffi/bindings/java/pom.xml + ffi/bindings/java/examples/pom.xml + ffi/bindings/dotnet/examples/master/Master.csproj + ffi/bindings/dotnet/examples/outstation/Outstation.csproj + ffi/bindings/c/CMakeLists.txt + guide/sitedata.json +) + +OLD="$(sed -n 's/^version = "\(.*\)"/\1/p' dnp3/Cargo.toml | head -n1)" +if [ -z "$OLD" ]; then + echo "could not determine current version from dnp3/Cargo.toml" >&2 + exit 1 +fi + +if [ "$OLD" = "$NEW" ]; then + echo "current version is already $NEW; nothing to do" >&2 + exit 1 +fi + +echo "bumping $OLD -> $NEW" +for f in "${FILES[@]}"; do + if ! grep -q -- "$OLD" "$f"; then + echo " warning: $OLD not found in $f" >&2 + continue + fi + sed -i "s/${OLD}/${NEW}/g" "$f" + echo " updated $f" +done + +echo "refreshing Cargo.lock" +cargo update -p dnp3 -p dnp3-ffi -p dnp3-ffi-java -p dnp3-schema -p dnp3-bindings --precise "$NEW" + +echo "verifying no '$OLD' references remain in the bumped files" +stray=() +for f in "${FILES[@]}"; do + if grep -q -- "$OLD" "$f"; then + stray+=("$f") + fi +done +if [ ${#stray[@]} -ne 0 ]; then + echo " version string still present in: ${stray[*]}" >&2 + exit 1 +fi +echo "done. review 'git diff', then update CHANGELOG.md." diff --git a/conformance/pom.xml b/conformance/pom.xml index 16b2c8d6..bccca688 100644 --- a/conformance/pom.xml +++ b/conformance/pom.xml @@ -11,7 +11,7 @@ UTF-8 2.13.4 - 1.7.0-RC1 + 1.7.0-RC2 0.1.0-SNAPSHOT 4.4.0 diff --git a/dnp3/Cargo.toml b/dnp3/Cargo.toml index feeffe49..55ac8c07 100644 --- a/dnp3/Cargo.toml +++ b/dnp3/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "dnp3" -version = "1.7.0-RC1" +version = "1.7.0-RC2" authors = ["Step Function I/O LLC "] description = "Rust implementation of DNP3 (IEEE 1815) with idiomatic bindings for C, C++, .NET, and Java" diff --git a/dnp3/codegen/pom.xml b/dnp3/codegen/pom.xml index c08c4b2d..589fc9a1 100644 --- a/dnp3/codegen/pom.xml +++ b/dnp3/codegen/pom.xml @@ -4,7 +4,7 @@ dev.gridio.dnp3 dnp3-model - 1.7.0-RC1 + 1.7.0-RC2 jar dnp3-rs model diff --git a/ffi/bindings/c/CMakeLists.txt b/ffi/bindings/c/CMakeLists.txt index c84328f5..fcf09348 100644 --- a/ffi/bindings/c/CMakeLists.txt +++ b/ffi/bindings/c/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.12) project(dnp3_c LANGUAGES C CXX) -set(DNP3_BACKUP_VERSION 1.7.0-RC1) +set(DNP3_BACKUP_VERSION 1.7.0-RC2) # Determine the architecture if(WIN32 AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64" AND CMAKE_SIZEOF_VOID_P EQUAL 8) diff --git a/ffi/bindings/dotnet/examples/master/Master.csproj b/ffi/bindings/dotnet/examples/master/Master.csproj index 9c35e903..caf398d8 100644 --- a/ffi/bindings/dotnet/examples/master/Master.csproj +++ b/ffi/bindings/dotnet/examples/master/Master.csproj @@ -13,7 +13,7 @@ - + diff --git a/ffi/bindings/dotnet/examples/outstation/Outstation.csproj b/ffi/bindings/dotnet/examples/outstation/Outstation.csproj index af899db8..b56ac247 100644 --- a/ffi/bindings/dotnet/examples/outstation/Outstation.csproj +++ b/ffi/bindings/dotnet/examples/outstation/Outstation.csproj @@ -13,7 +13,7 @@ - + diff --git a/ffi/bindings/java/examples/pom.xml b/ffi/bindings/java/examples/pom.xml index a2cd02c2..4db0483d 100644 --- a/ffi/bindings/java/examples/pom.xml +++ b/ffi/bindings/java/examples/pom.xml @@ -4,7 +4,7 @@ io.stepfunc.dnp3 examples - 1.7.0-RC1 + 1.7.0-RC2 1.8 @@ -16,7 +16,7 @@ io.stepfunc dnp3 - 1.7.0-RC1 + 1.7.0-RC2 diff --git a/ffi/bindings/java/pom.xml b/ffi/bindings/java/pom.xml index 7898b9ff..7b822a66 100644 --- a/ffi/bindings/java/pom.xml +++ b/ffi/bindings/java/pom.xml @@ -4,7 +4,7 @@ io.stepfunc dnp3-parent - 1.7.0-RC1 + 1.7.0-RC2 pom diff --git a/ffi/dnp3-bindings/Cargo.toml b/ffi/dnp3-bindings/Cargo.toml index 0b943314..02fb622c 100644 --- a/ffi/dnp3-bindings/Cargo.toml +++ b/ffi/dnp3-bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dnp3-bindings" -version = "1.7.0-RC1" +version = "1.7.0-RC2" # inherit from workspace rust-version.workspace = true diff --git a/ffi/dnp3-ffi-java/Cargo.toml b/ffi/dnp3-ffi-java/Cargo.toml index abe7fe6b..9e971c55 100644 --- a/ffi/dnp3-ffi-java/Cargo.toml +++ b/ffi/dnp3-ffi-java/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dnp3-ffi-java" -version = "1.7.0-RC1" +version = "1.7.0-RC2" build = "build.rs" # inherit from workspace diff --git a/ffi/dnp3-ffi/Cargo.toml b/ffi/dnp3-ffi/Cargo.toml index 0eba644c..a47e3676 100644 --- a/ffi/dnp3-ffi/Cargo.toml +++ b/ffi/dnp3-ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dnp3-ffi" -version = "1.7.0-RC1" +version = "1.7.0-RC2" # inherit from workspace rust-version.workspace = true diff --git a/ffi/dnp3-schema/Cargo.toml b/ffi/dnp3-schema/Cargo.toml index 300fe2ae..e6b83b7c 100644 --- a/ffi/dnp3-schema/Cargo.toml +++ b/ffi/dnp3-schema/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "dnp3-schema" # this version is what gets applied to the FFI libraries -version = "1.7.0-RC1" +version = "1.7.0-RC2" # inherit from workspace rust-version.workspace = true diff --git a/guide/sitedata.json b/guide/sitedata.json index e2480929..be1a15f2 100644 --- a/guide/sitedata.json +++ b/guide/sitedata.json @@ -1,4 +1,4 @@ { - "version": "1.7.0-RC1", + "version": "1.7.0-RC2", "github_url": "https://github.com/stepfunc/dnp3" } \ No newline at end of file From 80c4ff5514453c28a78b850502a33e5fd819b184 Mon Sep 17 00:00:00 2001 From: jadamcrain Date: Fri, 17 Jul 2026 10:04:08 -0700 Subject: [PATCH 2/2] document dependency policy in RELEASE.md --- RELEASE.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/RELEASE.md b/RELEASE.md index b14ed8da..6adf1ff9 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -43,6 +43,32 @@ cargo won't select by default.) Review and publish the **draft** GitHub release CI created. The publishers are idempotent, so re-running the tag's workflow safely retries any that failed. +## Dependencies + +Dependency security is handled **continuously**, not at release time: +`.github/workflows/security-audit.yml` runs `cargo audit` daily and on every +PR/`main` push that touches `Cargo.toml`/`Cargo.lock`, and fails on advisories. +Security patches land as their own PRs as advisories appear — they are not +batched onto releases. + +The release's dependency responsibilities are therefore narrow: + +- **Gate, don't churn:** the security audit must be green on the `prepare` PR + (it runs automatically because the PR touches `Cargo.lock`). Don't tag if it's + red. The prebuilt bindings (C/.NET/Java) freeze whatever is in `Cargo.lock` at + tag time, so a clean audit at the tag is what protects binding consumers — + pure-Rust crate consumers re-resolve on their own. +- **Freshen early, once per cycle:** do the routine "update dependencies" pass + at the *first* RC/milestone of a new minor version, not at each RC and not at + the final release. Late-cycle dependency churn undermines the stabilization + the RC process exists to provide. Subsequent RCs and the final release take + **security patches only** (targeted `cargo update -p `). +- **Respect deliberate pins:** some dependencies are exact-pinned for documented + reasons (e.g. `tokio-serial = "=5.4.5"`, pinned because upstream historically + shipped without changelogs, git tags, or GitHub releases, so bumps must be + reviewed by hand). Update these intentionally, in their own commit with a note + — never via a blanket `cargo update`. + ## CHANGELOG conventions - Each release candidate gets its own `### X.Y.Z-RCn ###` section while the