Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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 ###
Expand Down
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 80 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# 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.

## 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 <crate>`).
- **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
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.
71 changes: 71 additions & 0 deletions bump-version.sh
Original file line number Diff line number Diff line change
@@ -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 <new-version> (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."
2 changes: 1 addition & 1 deletion conformance/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<scala.version>2.13.4</scala.version>
<dnp3.version>1.7.0-RC1</dnp3.version>
<dnp3.version>1.7.0-RC2</dnp3.version>
<dnp4s.version>0.1.0-SNAPSHOT</dnp4s.version>
<scala-maven-plugin.version>4.4.0</scala-maven-plugin.version>
</properties>
Expand Down
2 changes: 1 addition & 1 deletion dnp3/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

[package]
name = "dnp3"
version = "1.7.0-RC1"
version = "1.7.0-RC2"

authors = ["Step Function I/O LLC <info@stepfunc.io>"]
description = "Rust implementation of DNP3 (IEEE 1815) with idiomatic bindings for C, C++, .NET, and Java"
Expand Down
2 changes: 1 addition & 1 deletion dnp3/codegen/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>dev.gridio.dnp3</groupId>
<artifactId>dnp3-model</artifactId>
<version>1.7.0-RC1</version>
<version>1.7.0-RC2</version>
<packaging>jar</packaging>

<name>dnp3-rs model</name>
Expand Down
2 changes: 1 addition & 1 deletion ffi/bindings/c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion ffi/bindings/dotnet/examples/master/Master.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="dnp3" Version="1.7.0-RC1" />
<PackageReference Include="dnp3" Version="1.7.0-RC2" />
</ItemGroup>
</Otherwise>
</Choose>
Expand Down
2 changes: 1 addition & 1 deletion ffi/bindings/dotnet/examples/outstation/Outstation.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="dnp3" Version="1.7.0-RC1" />
<PackageReference Include="dnp3" Version="1.7.0-RC2" />
</ItemGroup>
</Otherwise>
</Choose>
Expand Down
4 changes: 2 additions & 2 deletions ffi/bindings/java/examples/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>io.stepfunc.dnp3</groupId>
<artifactId>examples</artifactId>
<version>1.7.0-RC1</version>
<version>1.7.0-RC2</version>

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
Expand All @@ -16,7 +16,7 @@
<dependency>
<groupId>io.stepfunc</groupId>
<artifactId>dnp3</artifactId>
<version>1.7.0-RC1</version>
<version>1.7.0-RC2</version>
</dependency>
</dependencies>
</project>
2 changes: 1 addition & 1 deletion ffi/bindings/java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>io.stepfunc</groupId>
<artifactId>dnp3-parent</artifactId>
<version>1.7.0-RC1</version>
<version>1.7.0-RC2</version>
<packaging>pom</packaging>

<properties>
Expand Down
2 changes: 1 addition & 1 deletion ffi/dnp3-bindings/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion ffi/dnp3-ffi-java/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion ffi/dnp3-ffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion ffi/dnp3-schema/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion guide/sitedata.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"version": "1.7.0-RC1",
"version": "1.7.0-RC2",
"github_url": "https://github.com/stepfunc/dnp3"
}