From 022c2287abdae6b5d58835ba3653d3d4428b71d2 Mon Sep 17 00:00:00 2001 From: David Papp Date: Tue, 5 May 2026 17:37:35 +0200 Subject: [PATCH] chore: Clippy fixes and private crate integration --- .github/workflows/build.yml | 4 + .github/workflows/release.yaml | 107 ++++++++++++++++++++++++++ .github/workflows/wellness-check.yaml | 32 ++++++++ Cargo.toml | 8 ++ README.md | 51 ++++++++++++ build.rs | 3 + src/version1.rs | 10 +-- 7 files changed, 210 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/release.yaml create mode 100644 .github/workflows/wellness-check.yaml create mode 100644 build.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index afac59c..0bf0fb9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,6 +5,10 @@ jobs: build: name: Build, test, check runs-on: ubuntu-latest + env: + CARGO_REGISTRIES_GEN0SEC_INDEX: sparse+https://crates-internal.g0s.dev/api/v1/crates/ + CARGO_REGISTRIES_GEN0SEC_TOKEN: ${{ secrets.GEN0SEC_CARGO_TOKEN }} + CARGO_REGISTRIES_GEN0SEC_CREDENTIAL_PROVIDER: cargo:token steps: - uses: actions/checkout@v6 - uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..e68e22a --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,107 @@ +name: Release +on: + push: + tags: ['v*'] + workflow_dispatch: + inputs: + dry-run: + description: 'Run cargo publish with --dry-run (skips registry push and GH release)' + type: boolean + default: false + +jobs: + verify-version: + if: ${{ startsWith(github.ref, 'refs/tags/v') }} + runs-on: ubuntu-latest + outputs: + version: ${{ steps.v.outputs.version }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - id: v + run: | + TAG_VERSION="${GITHUB_REF_NAME#v}" + CRATE_VERSION=$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"([^"]+)".*/\1/') + if [ "$TAG_VERSION" != "$CRATE_VERSION" ]; then + echo "Tag version ($TAG_VERSION) does not match Cargo.toml version ($CRATE_VERSION)" >&2 + exit 1 + fi + echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT" + + package-crate: + needs: [verify-version] + runs-on: ubuntu-latest + permissions: + contents: read + env: + CARGO_REGISTRIES_GEN0SEC_INDEX: sparse+https://crates-internal.g0s.dev/api/v1/crates/ + CARGO_REGISTRIES_GEN0SEC_TOKEN: ${{ secrets.GEN0SEC_CARGO_TOKEN }} + CARGO_REGISTRIES_GEN0SEC_CREDENTIAL_PROVIDER: cargo:token + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + - name: cargo package + run: cargo package --registry gen0sec --locked + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 + with: + name: proxy-protocol-crate + path: target/package/proxy-protocol-${{ needs.verify-version.outputs.version }}.crate + if-no-files-found: error + retention-days: 7 + + publish: + needs: [verify-version, package-crate] + runs-on: ubuntu-latest + environment: release + permissions: + contents: read + env: + CARGO_REGISTRIES_GEN0SEC_INDEX: sparse+https://crates-internal.g0s.dev/api/v1/crates/ + CARGO_REGISTRIES_GEN0SEC_TOKEN: ${{ secrets.GEN0SEC_CARGO_TOKEN }} + CARGO_REGISTRIES_GEN0SEC_CREDENTIAL_PROVIDER: cargo:token + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + - name: Cargo publish + env: + DRY_RUN: ${{ inputs.dry-run }} + CARGO_HTTP_TIMEOUT: '300' + CARGO_HTTP_LOW_SPEED_LIMIT: '1' + CARGO_NET_RETRY: '5' + run: | + ARGS="--registry gen0sec --locked" + if [ "$DRY_RUN" = "true" ]; then + ARGS="$ARGS --dry-run" + fi + for attempt in 1 2 3; do + if cargo publish $ARGS; then exit 0; fi + echo "Publish attempt $attempt failed, retrying in 15s..." + sleep 15 + done + echo "Publish failed after 3 attempts" >&2 + exit 1 + + gh-release: + needs: [verify-version, package-crate, publish] + if: ${{ startsWith(github.ref, 'refs/tags/v') && inputs.dry-run != true }} + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + name: proxy-protocol-crate + path: release-assets + - name: SHA256 checksums + run: | + set -euo pipefail + cd release-assets + for f in *; do [ -f "$f" ] && sha256sum "$f" > "${f}.sha256"; done + ls -la + - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 + with: + draft: false + generate_release_notes: true + files: release-assets/* + make_latest: true diff --git a/.github/workflows/wellness-check.yaml b/.github/workflows/wellness-check.yaml new file mode 100644 index 0000000..b4fad74 --- /dev/null +++ b/.github/workflows/wellness-check.yaml @@ -0,0 +1,32 @@ +name: Wellness Check +on: + pull_request: + branches: [main, master] + +permissions: + contents: read + +jobs: + fmt-and-test: + runs-on: ubuntu-latest + env: + CARGO_REGISTRIES_GEN0SEC_INDEX: sparse+https://crates-internal.g0s.dev/api/v1/crates/ + CARGO_REGISTRIES_GEN0SEC_TOKEN: ${{ secrets.GEN0SEC_CARGO_TOKEN }} + CARGO_REGISTRIES_GEN0SEC_CREDENTIAL_PROVIDER: cargo:token + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable + with: + components: rustfmt, clippy + + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + + - name: Check formatting + run: cargo fmt --all -- --check + + - name: Check clippy + run: cargo clippy --all-targets --all-features -- --deny warnings + + - name: Run tests + run: cargo test -- --include-ignored diff --git a/Cargo.toml b/Cargo.toml index 2652210..09e98fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,14 @@ license = "MIT OR Apache-2.0" description = "PROXY protocol serializer and deserializer" documentation = "https://docs.rs/proxy-protocol/" repository = "https://github.com/Proximyst/proxy-protocol.git" +keywords = ["proxy", "proxy-protocol", "haproxy", "networking"] +categories = ["network-programming", "parser-implementations"] +links = "proxy-protocol" +readme = "README.md" + +[package.metadata.release] +publish = false +tag-name = "v{{version}}" [dependencies] snafu = "~0.9" diff --git a/README.md b/README.md index c4d0626..b2de240 100644 --- a/README.md +++ b/README.md @@ -22,3 +22,54 @@ additional terms or conditions. [LICENCE-APACHE-2.0]: ./LICENCE-APACHE-2.0 [Apache-2.0]: https://www.apache.org/licenses/LICENSE-2.0 [LICENCE-MIT]: ./LICENCE-MIT + +## Release Process + +`proxy-protocol` is published to the private `gen0sec` Cargo registry +(`https://crates-internal.g0s.dev`). Releases are driven by `vX.Y.Z` git +tags — `.github/workflows/release.yaml` handles build, publish, and +GitHub Release creation. + +### One-time setup + +- **Repo secret**: `GEN0SEC_CARGO_TOKEN` — bearer token for the registry. +- **`release` GitHub environment** (Settings → Environments → New) for + optional manual approval gating before publish. +- **Local cargo config** (`~/.cargo/config.toml`) for developers: + + ```toml + [registries.gen0sec] + index = "sparse+https://crates-internal.g0s.dev/api/v1/crates/" + credential-provider = ["cargo:token"] + token = "" + ``` + +### Cutting a release + +```bash +cargo install cargo-release +cargo release patch --execute # or minor / major / 1.2.3 +``` + +`cargo-release` bumps `Cargo.toml` + `Cargo.lock`, commits, creates +`vX.Y.Z`, and pushes; CI publishes on the tag push. +`[package.metadata.release] publish = false` keeps the local command +from publishing — that is left to CI. + +### CI jobs on `v*` tag + +1. **`verify-version`** — fails if tag does not match `Cargo.toml`. +2. **`package-crate`** — `cargo package --registry gen0sec --locked`, + uploads `proxy-protocol-X.Y.Z.crate`. +3. **`publish`** — `release` environment-gated `cargo publish` with + retry/timeout hardening. +4. **`gh-release`** — downloads `.crate`, generates SHA256 sidecars, + creates a GitHub Release. + +### Required Cargo.toml metadata + +The gen0sec registry enforces these `[package]` fields, missing ones +cause a `400 Bad Request`: + +`name`, `description`, `repository`, `license`, `authors`, `categories`, +`keywords`, `links`, `readme`. diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..c2bce4f --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + println!("cargo:rerun-if-changed=build.rs"); +} diff --git a/src/version1.rs b/src/version1.rs index bbf198c..313e9b5 100644 --- a/src/version1.rs +++ b/src/version1.rs @@ -410,7 +410,7 @@ mod encode_tests { #[test] fn test_unknown() { let encoded = encode(ProxyAddresses::Unknown); - assert!(matches!(encoded, Ok(_))); + assert!(encoded.is_ok()); assert_eq!(encoded.unwrap(), &b"PROXY UNKNOWN\r\n"[..]); } @@ -420,7 +420,7 @@ mod encode_tests { source: SocketAddrV4::new(Ipv4Addr::new(1, 2, 3, 4), 987), destination: SocketAddrV4::new(Ipv4Addr::new(255, 254, 253, 252), 12345), }); - assert!(matches!(encoded, Ok(_))); + assert!(encoded.is_ok()); assert_eq!( encoded.unwrap(), Bytes::from_static(&b"PROXY TCP4 1.2.3.4 255.254.253.252 987 12345\r\n"[..]), @@ -438,7 +438,7 @@ mod encode_tests { 0, ), }); - assert!(matches!(encoded, Ok(_))); + assert!(encoded.is_ok()); assert_eq!( encoded.unwrap(), Bytes::from_static( @@ -455,7 +455,7 @@ mod encode_tests { 0, ), }); - assert!(matches!(encoded, Ok(_))); + assert!(encoded.is_ok()); assert_eq!( encoded.unwrap(), Bytes::from_static(&b"PROXY TCP6 1:2:3:4:5:6:7:8 ffff:fffe::1:2:3 987 12345\r\n"[..]), @@ -465,7 +465,7 @@ mod encode_tests { source: SocketAddrV6::new(Ipv6Addr::new(1, 2, 3, 4, 5, 6, 7, 8), 987, 0, 0), destination: SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 1, 2, 3), 12345, 0, 0), }); - assert!(matches!(encoded, Ok(_))); + assert!(encoded.is_ok()); assert_eq!( encoded.unwrap(), Bytes::from_static(&b"PROXY TCP6 1:2:3:4:5:6:7:8 ::1:2:3 987 12345\r\n"[..]),