on:
push:
tags:
- "*-crate"
permissions:
contents: write # Changed from read to write for release creation
checks: write
name: Publish Crate Workflow
jobs:
audit:
name: Audit
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: "Generate Cargo.lock"
run: cargo generate-lockfile
- name: cargo-audit cache restore
id: cargo-audit_cache_restore
uses: actions/cache/restore@v4
with:
path: ~/.cargo/bin/cargo-audit
key: ${{ runner.os }}-cargo-audit
- run: cargo install cargo-audit
if: steps.cargo-audit_cache_restore.outputs.cache-hit != 'true'
- name: cargo-audit cache save
id: cargo-audit_cache_save
uses: actions/cache/save@v4
if: always() && steps.cargo-audit_cache_restore.outputs.cache-hit != 'true'
with:
path: ~/.cargo/bin/cargo-audit
key: ${{ runner.os }}-cargo-audit
- uses: rustsec/audit-check@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
build_and_test_linux:
name: Build and Test (Linux)
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Install Protobuf compiler
run: |
sudo apt-get update -qq
sudo apt-get install -y protobuf-compiler
- uses: dtolnay/rust-toolchain@stable
- name: Cache cargo registry restore
id: cargo_cache_restore_linux
uses: actions/cache/restore@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: "Build and test"
run: |
cargo install cargo-nextest
cargo nextest run --all-features --test-threads=1
- name: Cache cargo registry save
id: cargo_cache_save_linux
uses: actions/cache/save@v4
if: always() && steps.cargo_cache_restore_linux.outputs.cache-hit != 'true'
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
build_and_test_windows:
name: Build and Test (Windows)
runs-on: windows-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: Install Protobuf compiler
run: choco install protoc --no-progress -y
shell: powershell
- name: Cache cargo registry restore
id: cargo_cache_restore_windows
uses: actions/cache/restore@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- uses: dtolnay/rust-toolchain@stable
- name: "Build and test"
run: |
cargo install cargo-nextest
cargo nextest run --all-features --test-threads=1
- name: Cache cargo registry save
id: cargo_cache_save_windows
uses: actions/cache/save@v4
if: always() && steps.cargo_cache_restore_windows.outputs.cache-hit != 'true'
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
crates_io_publish:
name: Publish (crates.io)
needs:
- audit
- build_and_test_linux
- build_and_test_windows
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- name: Install Protobuf compiler
run: |
sudo apt-get update -qq
sudo apt-get install -y protobuf-compiler
- uses: dtolnay/rust-toolchain@stable
- name: cargo-release cache restore
id: cargo_release_cache_restore
uses: actions/cache/restore@v4
with:
path: ~/.cargo/bin/cargo-release
key: ${{ runner.os }}-cargo-release
- run: cargo install cargo-release
if: steps.cargo_release_cache_restore.outputs.cache-hit != 'true'
- name: cargo-release cache save
id: cargo_release_cache_save
uses: actions/cache/save@v4
if: always() && steps.cargo_release_cache_restore.outputs.cache-hit != 'true'
with:
path: ~/.cargo/bin/cargo-release
key: ${{ runner.os }}-cargo-release
- name: cargo login
run: |-
echo "${{ secrets.CRATES_IO_API_TOKEN }}" | cargo login
- name: "cargo release publish"
run: |-
cargo release \
publish \
--workspace \
--all-features \
--allow-branch HEAD \
--no-confirm \
--no-verify \
--execute
tag_docker_version:
name: Tag Docker Version
needs:
- crates_io_publish
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from tag
id: extract_version
run: |
# Extract version from tag (remove -crate suffix)
TAG_NAME=${GITHUB_REF#refs/tags/}
VERSION=${TAG_NAME%-crate}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "docker_tag_name=${VERSION}-docker" >> $GITHUB_OUTPUT
echo "Extracted version: $VERSION"
echo "Docker tag name will be: ${VERSION}-docker"
- name: Check if Docker tag exists
id: check_docker_tag
run: |
DOCKER_TAG_NAME="${{ steps.extract_version.outputs.docker_tag_name }}"
if git rev-parse "refs/tags/$DOCKER_TAG_NAME" >/dev/null 2>&1; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "Docker tag $DOCKER_TAG_NAME already exists"
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "Docker tag $DOCKER_TAG_NAME does not exist"
fi
- name: Create and push Docker tag
if: steps.check_docker_tag.outputs.exists == 'false'
run: |
DOCKER_TAG_NAME="${{ steps.extract_version.outputs.docker_tag_name }}"
VERSION="${{ steps.extract_version.outputs.version }}"
# Configure git
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Create annotated tag
git tag -a "$DOCKER_TAG_NAME" -m "Auto-tag for Docker version $VERSION"
# Push the tag
git push origin "$DOCKER_TAG_NAME"
echo "Created and pushed Docker tag: $DOCKER_TAG_NAME"
- name: Docker tag already exists
if: steps.check_docker_tag.outputs.exists == 'true'
run: |
echo "Docker tag ${{ steps.extract_version.outputs.docker_tag_name }} already exists, skipping tag creation"
create_github_release:
name: Create GitHub Release
needs:
- audit
- build_and_test_linux
- build_and_test_windows
- crates_io_publish
- tag_docker_version
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch full history for changelog generation
- name: Extract version from tag
id: extract_version
run: |
# Extract version from tag (remove -crate suffix)
TAG_NAME=${GITHUB_REF#refs/tags/}
VERSION=${TAG_NAME%-crate}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
- name: Build Changelog
id: build_changelog
uses: mikepenz/release-changelog-builder-action@v4
with:
configuration: |
{
"categories": [
{
"title": "## ๐ Features",
"labels": ["feature", "enhancement"]
},
{
"title": "## ๐ Bug Fixes",
"labels": ["bug", "fix"]
},
{
"title": "## ๐ Documentation",
"labels": ["documentation", "docs"]
},
{
"title": "## ๐ง Maintenance",
"labels": ["maintenance", "chore", "dependencies"]
},
{
"title": "## ๐ Security",
"labels": ["security"]
},
{
"title": "## โก Performance",
"labels": ["performance"]
},
{
"title": "## ๐งช Testing",
"labels": ["test", "testing"]
},
{
"title": "## ๐ Other Changes",
"labels": []
}
],
"template": "#{{CHANGELOG}}\n\n## ๐ฆ Installation\n\n### Cargo\n```bash\ncargo add foxy-io@${{ steps.extract_version.outputs.version }}\n```\n\n### From Source\n```bash\ngit clone https://github.com/johan-steffens/foxy.git\ncd foxy\ncargo build --release\n```\n\n## ๐ Links\n- [๐ฆ Crates.io](https://crates.io/crates/foxy-io)\n- [๐ Documentation](https://docs.rs/foxy-io)\n- [๐ Report Issues](https://github.com/johan-steffens/foxy/issues)\n\n---\n\n**Full Changelog**: https://github.com/johan-steffens/foxy/compare/{{PREVIOUS_TAG}}...{{TO_TAG}}"
}
toTag: ${{ steps.extract_version.outputs.tag_name }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.extract_version.outputs.tag_name }}
name: "foxy-io v${{ steps.extract_version.outputs.version }}"
body: ${{ steps.build_changelog.outputs.changelog }}
draft: false
prerelease: ${{ contains(steps.extract_version.outputs.version, 'alpha') || contains(steps.extract_version.outputs.version, 'beta') || contains(steps.extract_version.outputs.version, 'rc') }}
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}