name: Release
on:
release:
types: [published]
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
verify:
name: Verify (re-run CI before publishing)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
path: esp-emac
- uses: actions/checkout@v6
with:
repository: jethub-iot/eth-phy-rs
path: eth-phy
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
targets: riscv32imc-unknown-none-elf
- uses: Swatinem/rust-cache@v2
with:
workspaces: esp-emac
- working-directory: esp-emac
run: cargo fmt --all -- --check
- working-directory: esp-emac
run: cargo clippy --lib --features 'mdio-phy embassy-net async defmt' -- -D warnings
- working-directory: esp-emac
run: cargo test --features 'mdio-phy embassy-net async defmt'
- working-directory: esp-emac
env:
RUSTDOCFLAGS: --cfg docsrs
run: cargo doc --no-deps --target riscv32imc-unknown-none-elf --features 'mdio-phy embassy-net async defmt'
verify-xtensa:
name: Verify (xtensa example builds)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
path: esp-emac
- uses: actions/checkout@v6
with:
repository: jethub-iot/eth-phy-rs
path: eth-phy
- uses: esp-rs/xtensa-toolchain@v1.7
with:
default: true
buildtargets: esp32
ldproxy: false
- uses: Swatinem/rust-cache@v2
with:
workspaces: esp-emac
- working-directory: esp-emac
run: cargo build --release --example embassy_net_lan8720a --target xtensa-esp32-none-elf --features 'esp-hal mdio-phy embassy-net'
verify-msrv:
name: Verify MSRV 1.88 still builds (host)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
path: esp-emac
- uses: actions/checkout@v6
with:
repository: jethub-iot/eth-phy-rs
path: eth-phy
- uses: dtolnay/rust-toolchain@1.88.0
- uses: Swatinem/rust-cache@v2
with:
workspaces: esp-emac
- working-directory: esp-emac
run: cargo build --lib
- working-directory: esp-emac
run: cargo build --lib --features 'mdio-phy embassy-net async defmt'
verify-version:
name: Verify tag matches Cargo.toml
runs-on: ubuntu-latest
needs: [verify, verify-xtensa, verify-msrv]
outputs:
version: ${{ steps.tag.outputs.version }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
- name: Resolve version from tag
id: tag
run: |
set -euo pipefail
TAG='${{ github.event.release.tag_name }}'
# cargo / crates.io grammar: MAJOR.MINOR.PATCH with optional
# `-prerelease`. SemVer `+build` metadata is intentionally NOT
# accepted — cargo strips it on publish, so a `+build` tag
# would never match Cargo.toml or the registry, only opening
# a duplicate-publish footgun for no real benefit.
if [[ ! "$TAG" =~ ^v([0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.-]+)?)$ ]]; then
echo "::error::Tag '$TAG' does not match 'v<MAJOR>.<MINOR>.<PATCH>[-<prerelease>]' (build metadata '+...' is not accepted, see release.yml comment)"
exit 1
fi
echo "version=${BASH_REMATCH[1]}" >>"$GITHUB_OUTPUT"
- name: Confirm Cargo.toml agrees
run: |
set -euo pipefail
ACTUAL=$(cargo metadata --no-deps --format-version 1 \
| jq -r '.packages[] | select(.name == "esp-emac") | .version')
if [ "$ACTUAL" != '${{ steps.tag.outputs.version }}' ]; then
echo "::error::Cargo.toml says $ACTUAL, tag says ${{ steps.tag.outputs.version }}"
exit 1
fi
publish:
name: Publish to crates.io
runs-on: ubuntu-latest
needs: [verify, verify-xtensa, verify-msrv, verify-version]
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Skip if already on crates.io
id: check
run: |
set -euo pipefail
VERSION='${{ needs.verify-version.outputs.version }}'
if curl -fsSL "https://index.crates.io/es/p-/esp-emac" 2>/dev/null \
| jq -e --arg v "$VERSION" 'select(.vers == $v)' >/dev/null; then
echo "esp-emac@$VERSION already published — skipping"
echo "skip=true" >>"$GITHUB_OUTPUT"
else
echo "skip=false" >>"$GITHUB_OUTPUT"
fi
- name: Dry-run publish
if: steps.check.outputs.skip == 'false'
run: cargo publish --dry-run
- name: Publish to crates.io
if: steps.check.outputs.skip == 'false'
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.JETHUB_CRATES_TOKEN }}
run: cargo publish