name: CD
on:
workflow_dispatch:
inputs:
bump:
description: 'Version bump level'
required: true
type: choice
default: patch
options:
- patch
- minor
- major
skip_bump:
description: 'Skip version bump (publish current version only)'
required: false
type: boolean
default: false
env:
CARGO_TERM_COLOR: always
concurrency: release
jobs:
release:
environment: crates.io
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
- uses: Swatinem/rust-cache@v2
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Install cargo-release
uses: taiki-e/install-action@v2
with:
tool: cargo-release
- name: Bump version
if: ${{ !inputs.skip_bump }}
run: cargo release ${{ inputs.bump }} --execute --no-confirm
- name: Verify formatting
run: cargo fmt --check --all
- name: Run clippy
run: cargo clippy --all-features -- -D warnings
- name: Test funera_core
run: cargo test --lib --all-features -p funera-core
- name: Test funera-orchestrate
run: cargo test --lib --features deepseek,tool,security,sandbox,middleware,skill,funera-builtin-tools -p funera-orchestrate
- name: Build docs
run: cargo doc --no-deps --all-features
- name: Semver check
uses: obi1kenobi/cargo-semver-checks-action@v2
continue-on-error: true
- name: Cleanup semver-check artifacts
if: always()
run: rm -rf semver-checks
- name: Open release PR and merge
if: ${{ !inputs.skip_bump }}
run: |
# `cargo pkgid` yields `funera-core@X.Y.Z`; extract the bare version
# so tags/branches are named vX.Y.Z (no `vfunera-core@` prefix).
VERSION="$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "funera-core") | .version')"
BRANCH="release/v${VERSION}"
git push origin "HEAD:${BRANCH}"
PR_URL="$(gh pr create --base main --head "${BRANCH}" \
--title "chore: release v${VERSION}" \
--body "Automated release prepared by the CD workflow (version bump to v${VERSION}).")"
gh pr merge --merge --delete-branch "${PR_URL}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Push tag
if: ${{ !inputs.skip_bump }}
run: |
VERSION="$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "funera-core") | .version')"
git push origin "refs/tags/v${VERSION}"
- name: Publish funera_core
run: cargo publish -p funera-core --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
- name: Publish funera_builtin_tools
run: |
sleep 15
cargo publish -p funera-builtin-tools --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
- name: Publish funera-orchestrate
run: |
sleep 15
cargo publish -p funera-orchestrate --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
- name: Publish funera (root crate)
run: |
sleep 15
cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
- name: Create GitHub Release
run: |
VERSION="$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "funera-core") | .version')"
git fetch --tags
gh release create "v$VERSION" --generate-notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}