Skip to content
Merged
Show file tree
Hide file tree
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
20 changes: 8 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ on:
pull_request:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
CARGO_TERM_COLOR: always
RUSTFLAGS: -Dwarnings
Expand All @@ -14,6 +18,7 @@ jobs:
check:
name: Check
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -23,6 +28,7 @@ jobs:
fmt:
name: Format
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -33,6 +39,7 @@ jobs:
clippy:
name: Clippy
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
Expand All @@ -44,20 +51,9 @@ jobs:
test:
name: Test
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo test

build:
name: Build Release
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- run: cargo build --release
256 changes: 256 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
name: Release

on:
workflow_dispatch:
inputs:
version_bump:
description: 'Version bump type'
required: true
default: 'patch'
type: choice
options:
- patch
- minor
- major

concurrency:
group: release
cancel-in-progress: false

permissions:
contents: write

env:
CARGO_TERM_COLOR: always
RUSTFLAGS: -Dwarnings
BINARY_NAME: olx-tracker

jobs:
checks:
name: Checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: Format
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-targets
- name: Test
run: cargo test

create-tag:
name: Create Tag
needs: checks
runs-on: ubuntu-latest
outputs:
version: ${{ steps.bump.outputs.version }}
tag: ${{ steps.bump.outputs.tag }}
commit_sha: ${{ steps.commit.outputs.sha }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Verify on main branch
run: |
if [ "${{ github.ref }}" != "refs/heads/main" ]; then
echo "::error::Release must be run from main branch, not ${{ github.ref }}"
exit 1
fi

- name: Get current version
id: current
run: |
# Get version from Cargo.toml
VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Current version: $VERSION"

- name: Bump version
id: bump
run: |
CURRENT="${{ steps.current.outputs.version }}"
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT"

case "${{ inputs.version_bump }}" in
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
patch)
PATCH=$((PATCH + 1))
;;
esac

NEW_VERSION="$MAJOR.$MINOR.$PATCH"
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "tag=v$NEW_VERSION" >> $GITHUB_OUTPUT
echo "New version: $NEW_VERSION"

- name: Update Cargo.toml
run: |
sed -i 's/^version = ".*"/version = "${{ steps.bump.outputs.version }}"/' Cargo.toml
cat Cargo.toml | head -10

- name: Commit and tag
id: commit
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add Cargo.toml
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Cargo.lock not updated after version bump leaves repository in inconsistent state

When the release workflow bumps the version in Cargo.toml, it only commits Cargo.toml but does not regenerate Cargo.lock.

Click to expand

Mechanism

In the create-tag job, the version bump workflow:

  1. Updates Cargo.toml with sed (line 103)
  2. Only adds Cargo.toml to git: git add Cargo.toml (line 111)
  3. Commits and pushes (lines 112-115)

The Cargo.lock file contains the package's own version metadata. After this commit, the repository will have:

  • Cargo.toml with version X.Y.Z (new)
  • Cargo.lock still referencing version X.Y.Z-1 (old)

Impact

This leaves the repository in an inconsistent state where Cargo.toml and Cargo.lock have mismatched versions. While cargo build will fix this locally, the committed state in the repository is inconsistent, which could cause confusion or issues with reproducible builds.

Recommendation

Add a step to regenerate Cargo.lock after updating Cargo.toml:

- name: Update Cargo.toml
  run: |
    sed -i 's/^version = ".*"/version = "${{ steps.bump.outputs.version }}"/' Cargo.toml
    cargo generate-lockfile  # or cargo update --workspace
    cat Cargo.toml | head -10

- name: Commit and tag
  run: |
    ...
    git add Cargo.toml Cargo.lock
    ...
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

git commit -m "chore: bump version to ${{ steps.bump.outputs.version }}"
echo "sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
git tag -a "${{ steps.bump.outputs.tag }}" -m "Release ${{ steps.bump.outputs.tag }}"
git push origin main --follow-tags

build:
name: Build (${{ matrix.target }})
needs: create-tag
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: macos-latest
target: aarch64-apple-darwin
artifact: olx-tracker-macos-arm64
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
artifact: olx-tracker-linux-x64
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ needs.create-tag.outputs.tag }}

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}

- name: Cache
uses: Swatinem/rust-cache@v2
with:
key: release-${{ matrix.target }}

- name: Build
run: cargo build --release --target ${{ matrix.target }}

- name: Package (Unix)
run: |
cd target/${{ matrix.target }}/release
tar -czvf ../../../${{ matrix.artifact }}.tar.gz ${{ env.BINARY_NAME }}

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: ${{ matrix.artifact }}.tar.gz

release:
name: Create Release
needs: [create-tag, build]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ needs.create-tag.outputs.tag }}

- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Get previous tag
id: prev_tag
run: |
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
echo "tag=$PREV_TAG" >> $GITHUB_OUTPUT
echo "Previous tag: $PREV_TAG"

- name: Build Changelog
id: changelog
uses: mikepenz/release-changelog-builder-action@v5
with:
configurationJson: |
{
"categories": [
{ "title": "## Features", "labels": ["feature", "enhancement"] },
{ "title": "## Bug Fixes", "labels": ["bug", "fix"] },
{ "title": "## Documentation", "labels": ["documentation", "docs"] },
{ "title": "## Other Changes", "labels": [] }
],
"template": "#{{CHANGELOG}}\n\n**Full Changelog**: #{{RELEASE_DIFF}}",
"pr_template": "- #{{TITLE}} (#{{NUMBER}})",
"empty_template": "No pull requests since last release."
}
fromTag: ${{ steps.prev_tag.outputs.tag }}
toTag: ${{ needs.create-tag.outputs.tag }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.create-tag.outputs.tag }}
name: ${{ env.BINARY_NAME }} ${{ needs.create-tag.outputs.tag }}
body: |
## Installation

Download the appropriate binary for your platform:

| Platform | File |
|----------|------|
| macOS (Apple Silicon) | `olx-tracker-macos-arm64.tar.gz` |
| Linux (x64) | `olx-tracker-linux-x64.tar.gz` |

### Quick Install

```bash
# Linux/macOS
tar -xzf olx-tracker-*.tar.gz
chmod +x olx-tracker
./olx-tracker --help
```

${{ steps.changelog.outputs.changelog }}
files: artifacts/**/*.tar.gz
draft: false
prerelease: false

cleanup:
name: Cleanup on failure
needs: [create-tag, build]
if: failure() && needs.create-tag.result == 'success'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Delete tag and revert commit
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

echo "Deleting tag ${{ needs.create-tag.outputs.tag }}..."
git push --delete origin ${{ needs.create-tag.outputs.tag }} || true

echo "Reverting version bump commit ${{ needs.create-tag.outputs.commit_sha }}..."
git pull origin main
git revert ${{ needs.create-tag.outputs.commit_sha }} --no-edit
git push origin main