name: Release
permissions:
contents: write
on:
push:
tags:
- v*
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Run tests
run: cargo test --verbose
build:
needs: [test]
runs-on: ${{ matrix.job.os }}
strategy:
fail-fast: false
matrix:
job:
- { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , use-cross: false , extension: "" }
- { os: ubuntu-latest , target: x86_64-unknown-linux-musl , use-cross: true , extension: "" }
- { os: ubuntu-latest , target: armv7-unknown-linux-gnueabihf , use-cross: true , extension: "" }
- { os: ubuntu-latest , target: armv7-unknown-linux-musleabihf , use-cross: true , extension: "" }
- { os: ubuntu-latest , target: aarch64-unknown-linux-gnu , use-cross: true , extension: "" }
- { os: ubuntu-latest , target: aarch64-unknown-linux-musl , use-cross: true , extension: "" }
- { os: macos-latest , target: x86_64-apple-darwin , use-cross: false , extension: "" }
- { os: macos-latest , target: aarch64-apple-darwin , use-cross: false , extension: "" }
- { os: windows-latest , target: x86_64-pc-windows-msvc , use-cross: false , extension: .exe }
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Extract crate information
shell: bash
run: |
echo "PROJECT_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' Cargo.toml | head -n1)" >> $GITHUB_ENV
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.job.target }}
- name: Install cross
if: matrix.job.use-cross
run: cargo install cross --locked
- name: Build
shell: bash
run: |
if [ "${{ matrix.job.use-cross }}" = "true" ]; then
cross build --release --target ${{ matrix.job.target }}
else
cargo build --release --target ${{ matrix.job.target }}
fi
- name: Rename artifacts
shell: bash
run: |
mv target/${{ matrix.job.target }}/release/${{ env.PROJECT_NAME }}${{ matrix.job.extension }} target/${{ matrix.job.target }}/release/${{ env.PROJECT_NAME }}-${{ github.ref_name }}-${{ matrix.job.target }}${{ matrix.job.extension }}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.job.target }}
path: target/${{ matrix.job.target }}/release/${{ env.PROJECT_NAME }}-${{ github.ref_name }}-${{ matrix.job.target }}${{ matrix.job.extension }}
release:
needs: [build]
runs-on: ubuntu-latest
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: Release
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: artifacts/*
publish:
needs: [test]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Extract crate metadata
id: crate_metadata
shell: bash
run: |
CRATE_NAME=$(cargo metadata --no-deps --format-version 1 | python3 -c "import json, sys; print(json.load(sys.stdin)['packages'][0]['name'])")
CRATE_VERSION=$(cargo metadata --no-deps --format-version 1 | python3 -c "import json, sys; print(json.load(sys.stdin)['packages'][0]['version'])")
echo "crate_name=${CRATE_NAME}" >> "${GITHUB_OUTPUT}"
echo "crate_version=${CRATE_VERSION}" >> "${GITHUB_OUTPUT}"
- name: Check if version is already published
id: publish_guard
shell: bash
run: |
set -euo pipefail
PUBLISH_STATUS=$(curl --silent --output /dev/null --write-out "%{http_code}" \
-H "User-Agent: caesar_cipher_enc_dec-release (github-actions)" \
"https://crates.io/api/v1/crates/${{ steps.crate_metadata.outputs.crate_name }}/${{ steps.crate_metadata.outputs.crate_version }}")
if [ "${PUBLISH_STATUS}" = "200" ]; then
echo "should_publish=false" >> "${GITHUB_OUTPUT}"
echo "Version ${{ steps.crate_metadata.outputs.crate_version }} is already published for ${{ steps.crate_metadata.outputs.crate_name }}. Skipping publish."
elif [ "${PUBLISH_STATUS}" = "404" ]; then
echo "should_publish=true" >> "${GITHUB_OUTPUT}"
else
echo "Unexpected status from crates.io API: ${PUBLISH_STATUS}"
exit 1
fi
- name: Publish to crates.io
if: ${{ steps.publish_guard.outputs.should_publish == 'true' }}
run: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}