name: Publish to Crates.io
on:
workflow_dispatch:
inputs:
dry_run:
description: 'Perform a dry run (do not actually publish)'
required: false
default: false
type: boolean
workflow_run:
workflows: ["Build Artifact"]
types:
- completed
branches: [main]
permissions:
contents: write
pull-requests: read
env:
CARGO_TERM_COLOR: always
jobs:
publish:
name: ${{ inputs.dry_run && '🔥 Dry Run Publish' || '📦 Publish to Crates.io' }}
runs-on: ubuntu-latest
environment: production
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
- name: Setup Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Cache cargo registry
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Get package version
id: version
run: |
VERSION=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
echo "dry_run=${{ inputs.dry_run || false }}" >> $GITHUB_OUTPUT
- name: Check if tag exists
id: tag_check
run: |
if git rev-parse "v${{ steps.version.outputs.version }}" >/dev/null 2>&1; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "⚠️ Tag v${{ steps.version.outputs.version }} already exists!"
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "✅ Tag v${{ steps.version.outputs.version }} is new"
fi
- name: Build release
if: steps.tag_check.outputs.exists == 'false'
run: cargo build --release --verbose
- name: Run tests
if: steps.tag_check.outputs.exists == 'false'
run: cargo test --verbose
- name: Publish to crates.io (Dry Run)
if: steps.tag_check.outputs.exists == 'false' && steps.version.outputs.dry_run == 'true'
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_API_TOKEN }}
run: |
echo "🔥 DRY RUN: Would publish version ${{ steps.version.outputs.version }} to crates.io..."
cargo publish --dry-run --verbose
- name: Publish to crates.io
if: steps.tag_check.outputs.exists == 'false' && steps.version.outputs.dry_run == 'false'
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_API_TOKEN }}
run: |
echo "📦 Publishing version ${{ steps.version.outputs.version }} to crates.io..."
cargo publish --verbose
- name: Create Git tag
if: steps.tag_check.outputs.exists == 'false' && steps.version.outputs.dry_run == 'false'
run: |
git config user.name "otplus-actions[bot]"
git config user.email "otplus-actions[bot]@users.noreply.github.com"
git tag -a "${{ steps.version.outputs.tag }}" -m "Release version ${{ steps.version.outputs.version }}"
git push origin "${{ steps.version.outputs.tag }}"
- name: Create GitHub Release
if: steps.tag_check.outputs.exists == 'false' && steps.version.outputs.dry_run == 'false'
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.version.outputs.tag }}
release_name: Release ${{ steps.version.outputs.version }}
body: |
## Release Notes
### Changes in version ${{ steps.version.outputs.version }}
This release includes updates to the otplus-core library.
### Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
otplus-core = "${{ steps.version.outputs.version }}"
```
### Crates.io
This release is available on [crates.io](https://crates.io/crates/otplus-core/${{ steps.version.outputs.version }}).
draft: false
prerelease: false
- name: Upload release artifact
if: steps.tag_check.outputs.exists == 'false' && steps.version.outputs.dry_run == 'false'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: target/release/libotplus_core.rlib
asset_name: libotplus_core-${{ steps.version.outputs.version }}.rlib
asset_content_type: application/octet-stream
- name: Summary
run: |
echo "## 🚀 Publish Summary" >> $GITHUB_STEP_SUMMARY
echo "- **Version**: ${{ steps.version.outputs.version }}" >> $GITHUB_STEP_SUMMARY
echo "- **Tag**: ${{ steps.version.outputs.tag }}" >> $GITHUB_STEP_SUMMARY
echo "- **Trigger**: ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
if [ "${{ steps.version.outputs.dry_run }}" == "true" ]; then
echo "- **Mode**: 🔥 Dry Run (không thực sự publish)" >> $GITHUB_STEP_SUMMARY
else
echo "- **Mode**: 📦 Production Release" >> $GITHUB_STEP_SUMMARY
echo "- **Published**: ✅ Available on crates.io" >> $GITHUB_STEP_SUMMARY
fi
if [ "${{ steps.tag_check.outputs.exists }}" == "true" ]; then
echo "- **Status**: ⚠️ Version already published" >> $GITHUB_STEP_SUMMARY
else
echo "- **Status**: ✅ New version published successfully" >> $GITHUB_STEP_SUMMARY
fi