Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
265 changes: 69 additions & 196 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,25 @@ name: CI/CD
on:
push:
branches:
- main
- '**'
pull_request:
branches:
- main
workflow_dispatch:

env:
BINARY_NAME: modrinth-api
BUILD_WINDOWS: 1
BUILD_LINUX: 1
CARGO_TERM_COLOR: always

jobs:
build:
name: Build (Debug/Release based on ref)
runs-on: ubuntu-latest
test_and_lint:
name: Test & Lint (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-pc-windows-gnu
os: windows-latest
rust: stable
build_os: windows
arch: x64
- target: i686-pc-windows-gnu
os: windows-latest
rust: stable
build_os: windows
arch: x86
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
rust: stable
build_os: linux
arch: x64

os: [ ubuntu-latest, windows-latest, macos-latest ]
rust: [ stable ]
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -42,65 +30,28 @@ jobs:
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
components: rustfmt
override: true
components: rustfmt, clippy

- name: Install MinGW-w64 toolchain
if: matrix.build_os == 'windows'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends mingw-w64
- name: Check formatting
run: cargo fmt --all -- --check

- name: Determine build type
id: build_type
run: |
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
echo "build_mode=release" >> $GITHUB_OUTPUT
else
echo "build_mode=debug" >> $GITHUB_OUTPUT
fi
- name: Clippy Lints
run: cargo clippy --all-targets --all-features -- -D warnings

- name: Build project (${{ matrix.build_os }} - ${{ matrix.arch }})
if: |
(matrix.build_os == 'windows' && env.BUILD_WINDOWS == '1') ||
(matrix.build_os == 'linux' && env.BUILD_LINUX == '1')
run: cargo build ${{ steps.build_type.outputs.build_mode == 'release' && '--release' || '' }} --target ${{ matrix.target }}

- name: Create artifacts directory
shell: bash
run: mkdir -p artifacts

- name: Copy binary to artifacts (${{ matrix.build_os }} - ${{ matrix.arch }})
if: |
(matrix.build_os == 'windows' && env.BUILD_WINDOWS == '1') ||
(matrix.build_os == 'linux' && env.BUILD_LINUX == '1')
shell: bash
run: |
BUILD_MODE="${{ steps.build_type.outputs.build_mode }}"
TARGET_DIR="target/${{ matrix.target }}/${BUILD_MODE}"
SOURCE_EXE="${TARGET_DIR}/${{ env.BINARY_NAME }}.exe"
SOURCE_BIN="${TARGET_DIR}/${{ env.BINARY_NAME }}"

if [[ "${{ matrix.build_os }}" == "windows" ]]; then
cp "${SOURCE_EXE}" "artifacts/${{ env.BINARY_NAME }}-${{ matrix.target }}.exe"
else
cp "${SOURCE_BIN}" "artifacts/${{ env.BINARY_NAME }}-${{ matrix.target }}"
fi
- name: Run tests
run: cargo test --all-targets --all-features --verbose

- name: Upload Build Artifacts (${{ steps.build_type.outputs.build_mode }})
uses: actions/upload-artifact@v4
with:
name: ${{ env.BINARY_NAME }}-${{ matrix.build_os }}-${{ matrix.arch }}-${{ steps.build_type.outputs.build_mode }}
path: artifacts/*
if-no-files-found: error
- name: Build documentation (as a check)
run: cargo doc --no-deps --all-features

check_version:
name: Check Version
check_version_for_release:
name: Check Version for Release
runs-on: ubuntu-latest
outputs:
should_release: ${{ steps.check_version_logic.outputs.should_release }}
should_release: ${{ steps.check_logic.outputs.should_release }}
current_version: ${{ steps.get_version.outputs.current_version }}
is_prerelease: ${{ steps.check_logic.outputs.is_prerelease }}
tag_name: ${{ steps.check_logic.outputs.tag_name }}
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -114,147 +65,69 @@ jobs:
echo "current_version=$VERSION" >> $GITHUB_OUTPUT
echo "Current Cargo.toml version: $VERSION"

- name: Get latest release tag
id: get_latest_tag
run: |
LATEST_TAG=$(git tag --sort=-v:refname | head -n 1)
echo "latest_tag=$LATEST_TAG" >> $GITHUB_OUTPUT
echo "Latest Git tag: $LATEST_TAG"

- name: Check if version has changed
id: check_version_logic
- name: Determine if release is needed and if it's a prerelease
id: check_logic
run: |
CURRENT_VERSION="${{ steps.get_version.outputs.current_version }}"
LATEST_TAG="${{ steps.get_latest_tag.outputs.latest_tag }}"
TAG_NAME="v${CURRENT_VERSION}"
SHOULD_RELEASE="false"
IS_PRERELEASE="false"

if [[ -n "$LATEST_TAG" ]]; then
LATEST_VERSION_FROM_TAG="${LATEST_TAG#v}" # Удаляем 'v' если есть
if [[ "$CURRENT_VERSION" != "$LATEST_VERSION_FROM_TAG" ]]; then
SHOULD_RELEASE="true"
echo "Version changed: $LATEST_VERSION_FROM_TAG -> $CURRENT_VERSION. Should release."
else
echo "Version $CURRENT_VERSION is the same as latest tag $LATEST_TAG. No release needed."
fi
if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
echo "Tag $TAG_NAME already exists. No release needed for version $CURRENT_VERSION."
else
echo "Tag $TAG_NAME does not exist for version $CURRENT_VERSION. A release should be created."
SHOULD_RELEASE="true"
echo "No previous tags found. Should release version $CURRENT_VERSION."
fi
echo "should_release=$SHOULD_RELEASE" >> $GITHUB_OUTPUT

build_release:
name: Build Release Binaries
needs: [ check_version ]
if: needs.check_version.outputs.should_release == 'true' && github.ref_name == 'main'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-pc-windows-gnu
os: windows-latest
rust: stable
build_os: windows
arch: x64
- target: i686-pc-windows-gnu
os: windows-latest
rust: stable
build_os: windows
arch: x86
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
rust: stable
build_os: linux
arch: x64
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
components: rustfmt
override: true

- name: Install MinGW-w64 toolchain
if: matrix.build_os == 'windows'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends mingw-w64

- name: Build Release Binaries (${{ matrix.build_os }} - ${{ matrix.arch }})
run: cargo build --release --target ${{ matrix.target }}

- name: Create release package directory
shell: bash
run: mkdir -p release-package

- name: Copy release binary to package (${{ matrix.build_os }} - ${{ matrix.arch }})
shell: bash
run: |
TARGET_DIR="target/${{ matrix.target }}/release"
DEST_DIR="release-package" # Всегда одна и та же папка назначения для артефакта
SOURCE_EXE="${TARGET_DIR}/${{ env.BINARY_NAME }}.exe"
SOURCE_BIN="${TARGET_DIR}/${{ env.BINARY_NAME }}"

if [[ "${{ matrix.build_os }}" == "windows" ]]; then
cp "${SOURCE_EXE}" "${DEST_DIR}/${{ env.BINARY_NAME }}-${{ matrix.target }}.exe"
if echo "$CURRENT_VERSION" | grep -q '-'; then
IS_PRERELEASE="true"
echo "Version $CURRENT_VERSION is a pre-release."
else
cp "${SOURCE_BIN}" "${DEST_DIR}/${{ env.BINARY_NAME }}-${{ matrix.target }}"
echo "Version $CURRENT_VERSION is a full release."
fi

- name: Upload Release Build Artifact
uses: actions/upload-artifact@v4
with:
name: release-asset-${{ matrix.target }}
path: release-package/*
if-no-files-found: error
echo "should_release=$SHOULD_RELEASE" >> $GITHUB_OUTPUT
echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT

publish_release:
name: Publish GitHub Release
needs: [ check_version, build_release ]
if: needs.check_version.outputs.should_release == 'true' && github.ref_name == 'main'
publish_crate_release:
name: Create Tag and Publish GitHub Release
if: github.ref == 'refs/heads/main' && needs.check_version_for_release.outputs.should_release == 'true'
needs: [ test_and_lint, check_version_for_release ]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Checkout code (for release-drafter)
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Download all release assets
uses: actions/download-artifact@v4
with:
path: all-release-assets

- name: List downloaded files (for debugging)
- name: Configure Git
run: |
echo "Downloaded artifacts will be in subdirectories under all-release-assets/"
ls -R all-release-assets
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"

- name: Create Release Notes
id: release_notes
uses: release-drafter/release-drafter@v6
- name: Create and Push Git Tag
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
name: Release v${{ needs.check_version.outputs.current_version }}
tag: v${{ needs.check_version.outputs.current_version }}
TAG_NAME: ${{ needs.check_version_for_release.outputs.tag_name }}
run: |
echo "Creating and pushing tag $TAG_NAME"
git tag "$TAG_NAME" -m "Release $TAG_NAME"
git push origin "$TAG_NAME"

- name: Upload Release Assets to GitHub Release
uses: softprops/action-gh-release@v2
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v${{ needs.check_version.outputs.current_version }}
name: Release v${{ needs.check_version.outputs.current_version }}
body: ${{ steps.release_notes.outputs.body }}
files: |
all-release-assets/release-asset-*/*
fail_on_unmatched_files: true
draft: false
prerelease: false
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ needs.check_version_for_release.outputs.tag_name }}
IS_PRERELEASE: ${{ needs.check_version_for_release.outputs.is_prerelease }}
run: |
PRERELEASE_OPTION=""
if [[ "$IS_PRERELEASE" == "true" ]]; then
PRERELEASE_OPTION="--prerelease"
fi

echo "Creating GitHub release for tag $TAG_NAME"
gh release create "$TAG_NAME" \
--title "Release $TAG_NAME" \
--generate-notes \
$PRERELEASE_OPTION
Loading