ci: improve release process reliability
- Add Docker build test to CI (rust.yml) to catch Dockerfile issues early - Add publish-release job to release.yml that un-drafts the release before triggering Homebrew/Chocolatey, preventing 404 errors - Add pre-release validation script (scripts/pre-release-check.sh) that checks version consistency, changelog, code quality, and Dockerfile - Update RELEASE.md with new pre-release check step
This commit is contained in:
@@ -358,6 +358,25 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
# Publish the release (un-draft) after all assets are uploaded.
|
||||
# This ensures downstream jobs (Homebrew, Chocolatey) can download assets.
|
||||
publish-release:
|
||||
name: publish-release
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- create-release
|
||||
- upload-arm-static
|
||||
- upload-android-static
|
||||
- package-installers
|
||||
- package-macos
|
||||
- package-windows
|
||||
if: always() && needs.create-release.result == 'success'
|
||||
steps:
|
||||
- name: Publish release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: gh release edit ${{ github.ref_name }} --draft=false --repo ${{ github.repository }}
|
||||
|
||||
trigger-bsd-build:
|
||||
name: trigger-bsd-build
|
||||
runs-on: ubuntu-latest
|
||||
@@ -375,7 +394,7 @@ jobs:
|
||||
trigger-homebrew-update:
|
||||
name: trigger-homebrew-update
|
||||
runs-on: ubuntu-latest
|
||||
needs: create-release
|
||||
needs: publish-release
|
||||
steps:
|
||||
- name: Trigger Homebrew formula update
|
||||
run: |
|
||||
@@ -388,7 +407,7 @@ jobs:
|
||||
trigger-chocolatey-update:
|
||||
name: trigger-chocolatey-update
|
||||
runs-on: ubuntu-latest
|
||||
needs: create-release
|
||||
needs: publish-release
|
||||
steps:
|
||||
- name: Trigger Chocolatey package update
|
||||
run: |
|
||||
|
||||
@@ -10,6 +10,8 @@ on:
|
||||
- 'assets/services'
|
||||
- 'assets/oui.gz'
|
||||
- 'build.rs'
|
||||
- 'benches/**'
|
||||
- 'Dockerfile'
|
||||
- '.github/workflows/rust.yml'
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
@@ -20,6 +22,8 @@ on:
|
||||
- 'assets/services'
|
||||
- 'assets/oui.gz'
|
||||
- 'build.rs'
|
||||
- 'benches/**'
|
||||
- 'Dockerfile'
|
||||
- '.github/workflows/rust.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -48,3 +52,19 @@ jobs:
|
||||
run: cargo install cargo-audit --locked
|
||||
- name: Run security audit
|
||||
run: cargo audit
|
||||
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
- name: Build Docker image
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
push: false
|
||||
load: true
|
||||
tags: rustnet:ci-test
|
||||
- name: Verify Docker image
|
||||
run: docker run --rm rustnet:ci-test --version
|
||||
|
||||
+18
-6
@@ -4,9 +4,20 @@ This document is for maintainers releasing new versions of RustNet.
|
||||
|
||||
## Creating a New Release
|
||||
|
||||
### 1. Test Platform Builds
|
||||
### 1. Run Pre-Release Checks
|
||||
|
||||
Before making any release changes, verify all platform builds succeed on the current main branch:
|
||||
After updating versions and changelog, run the pre-release validation script:
|
||||
|
||||
```bash
|
||||
./scripts/pre-release-check.sh 1.2.0
|
||||
```
|
||||
|
||||
This validates version consistency, changelog entries, code quality (fmt/clippy/test),
|
||||
Dockerfile correctness, and git status. Fix any errors before proceeding.
|
||||
|
||||
### 2. Test Platform Builds
|
||||
|
||||
Before tagging, verify all platform builds succeed on the current main branch:
|
||||
|
||||
```bash
|
||||
# Ensure you're on the main branch with latest changes
|
||||
@@ -21,7 +32,7 @@ git pull origin main
|
||||
|
||||
This catches cross-platform and static linking issues before you invest time in release prep.
|
||||
|
||||
### 2. Prepare the Release
|
||||
### 3. Prepare the Release
|
||||
|
||||
Update version in `Cargo.toml`, `rpm/rustnet.spec`, and update `CHANGELOG.md` with release notes:
|
||||
|
||||
@@ -35,7 +46,7 @@ cargo build --release
|
||||
cargo test
|
||||
```
|
||||
|
||||
### 3. Commit Release Changes
|
||||
### 4. Commit Release Changes
|
||||
|
||||
```bash
|
||||
# Stage and commit the version and changelog changes
|
||||
@@ -47,7 +58,7 @@ git commit -m "Release v0.3.0
|
||||
- And more changes"
|
||||
```
|
||||
|
||||
### 4. Create and Push Git Tag
|
||||
### 5. Create and Push Git Tag
|
||||
|
||||
```bash
|
||||
# Create an annotated tag matching the version in Cargo.toml
|
||||
@@ -69,7 +80,7 @@ git push origin v0.3.0
|
||||
- Create a draft GitHub release with all artifacts attached
|
||||
- Upload all binaries and installers to the release
|
||||
|
||||
### 5. Finalize the Release
|
||||
### 6. Finalize the Release
|
||||
|
||||
Once the GitHub Actions workflow completes (~15-20 minutes):
|
||||
|
||||
@@ -110,6 +121,7 @@ The release process is fully automated via [`.github/workflows/release.yml`](.gi
|
||||
|
||||
Before pushing the tag, ensure:
|
||||
|
||||
- [ ] Pre-release checks pass: `./scripts/pre-release-check.sh x.y.z`
|
||||
- [ ] Test Platform Builds workflow passes for all platforms (including static)
|
||||
- [ ] Version number updated in `Cargo.toml`
|
||||
- [ ] Version number updated in `rpm/rustnet.spec` (line 5: `Version: x.y.z`)
|
||||
|
||||
Executable
+165
@@ -0,0 +1,165 @@
|
||||
#!/usr/bin/env bash
|
||||
# Pre-release validation script for RustNet.
|
||||
# Run this before tagging a release to catch common issues.
|
||||
#
|
||||
# Usage: ./scripts/pre-release-check.sh [version]
|
||||
# e.g.: ./scripts/pre-release-check.sh 1.2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
ERRORS=0
|
||||
WARNINGS=0
|
||||
|
||||
pass() { echo -e " ${GREEN}✓${NC} $1"; }
|
||||
fail() { echo -e " ${RED}✗${NC} $1"; ERRORS=$((ERRORS + 1)); }
|
||||
warn() { echo -e " ${YELLOW}!${NC} $1"; WARNINGS=$((WARNINGS + 1)); }
|
||||
|
||||
VERSION="${1:-}"
|
||||
|
||||
echo "RustNet Pre-Release Checks"
|
||||
echo "=========================="
|
||||
echo
|
||||
|
||||
# --- Version consistency ---
|
||||
echo "Version consistency:"
|
||||
|
||||
CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
|
||||
RPM_VERSION=$(grep '^Version:' rpm/rustnet.spec | awk '{print $2}')
|
||||
|
||||
if [ -n "$VERSION" ]; then
|
||||
if [ "$CARGO_VERSION" = "$VERSION" ]; then
|
||||
pass "Cargo.toml version: $CARGO_VERSION"
|
||||
else
|
||||
fail "Cargo.toml version is $CARGO_VERSION, expected $VERSION"
|
||||
fi
|
||||
if [ "$RPM_VERSION" = "$VERSION" ]; then
|
||||
pass "rpm/rustnet.spec version: $RPM_VERSION"
|
||||
else
|
||||
fail "rpm/rustnet.spec version is $RPM_VERSION, expected $VERSION"
|
||||
fi
|
||||
else
|
||||
if [ "$CARGO_VERSION" = "$RPM_VERSION" ]; then
|
||||
pass "Versions match: Cargo.toml=$CARGO_VERSION, rustnet.spec=$RPM_VERSION"
|
||||
else
|
||||
fail "Version mismatch: Cargo.toml=$CARGO_VERSION, rustnet.spec=$RPM_VERSION"
|
||||
fi
|
||||
VERSION="$CARGO_VERSION"
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
# --- Changelog ---
|
||||
echo "Changelog:"
|
||||
|
||||
if grep -q "## \[$VERSION\]" CHANGELOG.md; then
|
||||
pass "CHANGELOG.md has entry for $VERSION"
|
||||
else
|
||||
fail "CHANGELOG.md missing entry for [$VERSION]"
|
||||
fi
|
||||
|
||||
if grep -q "\[$VERSION\]: https://github.com" CHANGELOG.md; then
|
||||
pass "CHANGELOG.md has comparison link for $VERSION"
|
||||
else
|
||||
fail "CHANGELOG.md missing comparison link for $VERSION"
|
||||
fi
|
||||
|
||||
UNRELEASED_CONTENT=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{found=0} found{print}' CHANGELOG.md | grep -v '^$' | head -1)
|
||||
if [ -z "$UNRELEASED_CONTENT" ]; then
|
||||
pass "[Unreleased] section is empty (content moved to $VERSION)"
|
||||
else
|
||||
warn "[Unreleased] section still has content"
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
# --- Build checks ---
|
||||
echo "Build checks:"
|
||||
|
||||
if cargo fmt --check > /dev/null 2>&1; then
|
||||
pass "cargo fmt"
|
||||
else
|
||||
fail "cargo fmt --check has formatting issues"
|
||||
fi
|
||||
|
||||
if cargo clippy -- -D warnings > /dev/null 2>&1; then
|
||||
pass "cargo clippy"
|
||||
else
|
||||
fail "cargo clippy has warnings"
|
||||
fi
|
||||
|
||||
if cargo test > /dev/null 2>&1; then
|
||||
pass "cargo test"
|
||||
else
|
||||
fail "cargo test failed"
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
# --- Dockerfile ---
|
||||
echo "Dockerfile:"
|
||||
|
||||
CARGO_BENCHES=$(grep -c '^\[\[bench\]\]' Cargo.toml || true)
|
||||
if [ "$CARGO_BENCHES" -gt 0 ]; then
|
||||
if grep -q 'COPY benches' Dockerfile; then
|
||||
pass "Dockerfile copies benches/ directory"
|
||||
else
|
||||
fail "Cargo.toml defines $CARGO_BENCHES bench(es) but Dockerfile doesn't COPY benches/"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check that all include!() / assets referenced at compile time are in Dockerfile
|
||||
for asset in $(grep -roh 'include_bytes!("[^"]*")' src/ 2>/dev/null | sed 's/include_bytes!("//;s/")//' | sort -u); do
|
||||
# Resolve relative paths from src/
|
||||
resolved=$(cd src && realpath --relative-to=.. "$asset" 2>/dev/null || echo "$asset")
|
||||
if grep -q "$resolved\|$(basename "$resolved")" Dockerfile; then
|
||||
pass "Dockerfile includes compile-time asset: $resolved"
|
||||
else
|
||||
fail "Compile-time asset $resolved not found in Dockerfile COPY commands"
|
||||
fi
|
||||
done
|
||||
|
||||
if docker info > /dev/null 2>&1; then
|
||||
echo
|
||||
echo "Docker build test:"
|
||||
if docker build -t rustnet:pre-release-test . > /dev/null 2>&1; then
|
||||
pass "Docker image builds successfully"
|
||||
docker rmi rustnet:pre-release-test > /dev/null 2>&1 || true
|
||||
else
|
||||
fail "Docker build failed"
|
||||
fi
|
||||
else
|
||||
warn "Docker not available, skipping Docker build test"
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
# --- Git status ---
|
||||
echo "Git status:"
|
||||
|
||||
if git diff --quiet Cargo.lock; then
|
||||
pass "Cargo.lock is up to date"
|
||||
else
|
||||
fail "Cargo.lock has uncommitted changes (run cargo build)"
|
||||
fi
|
||||
|
||||
if [ -z "$(git status --porcelain -- src/ Cargo.toml Cargo.lock CHANGELOG.md rpm/)" ]; then
|
||||
pass "No uncommitted changes in release files"
|
||||
else
|
||||
warn "Uncommitted changes in release files"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=========================="
|
||||
if [ "$ERRORS" -gt 0 ]; then
|
||||
echo -e "${RED}$ERRORS error(s)${NC}, $WARNINGS warning(s) — fix errors before releasing"
|
||||
exit 1
|
||||
elif [ "$WARNINGS" -gt 0 ]; then
|
||||
echo -e "${GREEN}0 errors${NC}, ${YELLOW}$WARNINGS warning(s)${NC} — review warnings before releasing"
|
||||
else
|
||||
echo -e "${GREEN}All checks passed!${NC} Ready to tag v$VERSION"
|
||||
fi
|
||||
Reference in New Issue
Block a user