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
10 changes: 10 additions & 0 deletions .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[bumpversion]
current_version = 1.0.0
commit = True
tag = True
tag_name = v{new_version}
message = [RELEASE] Bump version: {current_version} → {new_version}

[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ env:
jobs:
test:
name: Test Suite
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
python-version: ['3.9']

steps:
- name: Checkout code
Expand Down Expand Up @@ -43,7 +43,7 @@ jobs:

integration-test:
name: Integration Tests
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
needs: test
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop'

Expand Down
265 changes: 265 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
name: Release

on:
push:
branches:
- main
- develop
tags:
- 'v*.*.*'
workflow_dispatch:
inputs:
version_type:
description: 'Type of version bump'
required: true
default: 'patch'
type: choice
options:
- patch
- minor
- major
branch:
description: 'Branch to release from'
required: true
default: 'main'
type: choice
options:
- main
- develop
skip_tests:
description: 'Skip tests before release'
required: false
default: false
type: boolean

env:
PYTHON_VERSION: '3.9'

jobs:
# Test before releasing - reuse existing CI strategy
test:
name: Test Suite
runs-on: ubuntu-latest
if: ${{ !inputs.skip_tests }}
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Run linting
run: |
make lint
- name: Run formatting
run: |
make format
- name: Run tests
run: |
make test

integration-test:
name: Integration Tests
runs-on: ubuntu-latest
needs: test
if: ${{ !inputs.skip_tests && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') }}

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python 3.9
uses: actions/setup-python@v4
with:
python-version: '3.9'

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Run integration tests
env:
LABELLERR_API_KEY: ${{ secrets.LABELLERR_API_KEY }}
LABELLERR_API_SECRET: ${{ secrets.LABELLERR_API_SECRET }}
LABELLERR_CLIENT_ID: ${{ secrets.LABELLERR_CLIENT_ID }}
LABELLERR_TEST_EMAIL: ${{ secrets.LABELLERR_TEST_EMAIL }}
run: |
python -m pytest labellerr_use_case_tests.py -v

release:
name: Create Release
runs-on: ubuntu-latest
needs: [test, integration-test]
if: always() && (needs.test.result == 'success' || needs.test.result == 'skipped') && (needs.integration-test.result == 'success' || needs.integration-test.result == 'skipped')
outputs:
version: ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.tag }}
ticket: ${{ steps.ticket.outputs.ticket }}

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Install bump2version
run: pip install bump2version

- name: Configure git
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"

- name: Extract ticket from commit or branch
id: ticket
run: |
# Extract LABIMP ticket from latest commit message or branch name
COMMIT_MSG=$(git log -1 --pretty=format:"%s")
TICKET=$(echo "$COMMIT_MSG" | grep -oE 'LABIMP-[0-9]+' | head -1 || echo "")
if [ -z "$TICKET" ]; then
TICKET=$(echo "${{ github.head_ref || github.ref_name }}" | grep -oE 'LABIMP-[0-9]+' | head -1 || echo "RELEASE")
fi
echo "ticket=$TICKET" >> $GITHUB_OUTPUT
echo "Found ticket: $TICKET"

- name: Determine version bump type
id: bump_type
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "type=${{ inputs.version_type }}" >> $GITHUB_OUTPUT
elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
echo "type=patch" >> $GITHUB_OUTPUT
elif [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then
echo "type=minor" >> $GITHUB_OUTPUT
else
echo "type=patch" >> $GITHUB_OUTPUT
fi

- name: Get current version
id: current_version
run: |
VERSION=$(grep '^version = ' pyproject.toml | cut -d'"' -f2)
echo "current=$VERSION" >> $GITHUB_OUTPUT

- name: Bump version
id: version
run: |
BUMP_TYPE=${{ steps.bump_type.outputs.type }}

# Create .bumpversion.cfg with LABIMP commit message format
cat > .bumpversion.cfg << EOF
[bumpversion]
current_version = ${{ steps.current_version.outputs.current }}
commit = True
tag = True
tag_name = v{new_version}
message = [${{ steps.ticket.outputs.ticket }}] Bump version: {current_version} → {new_version}

[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"
EOF

# Bump the version
bump2version $BUMP_TYPE

# Get the new version
NEW_VERSION=$(grep '^version = ' pyproject.toml | cut -d'"' -f2)
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "tag=v$NEW_VERSION" >> $GITHUB_OUTPUT

- name: Push changes
run: |
git push origin ${{ github.ref_name }}
git push origin ${{ steps.version.outputs.tag }}

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.tag }}
name: '[${{ steps.ticket.outputs.ticket }}] Release ${{ steps.version.outputs.tag }}'
draft: false
prerelease: ${{ github.ref == 'refs/heads/develop' }}
generate_release_notes: true
body: |
## [${{ steps.ticket.outputs.ticket }}] Changes in ${{ steps.version.outputs.tag }}

### What's Changed
- Automated release from `${{ github.ref_name }}` branch
- Version bumped from `${{ steps.current_version.outputs.current }}` to `${{ steps.version.outputs.version }}`

### Branch Strategy
- **Main branch** releases are production-ready patches
- **Develop branch** releases are pre-release minor versions for testing

build:
name: Build Package
runs-on: ubuntu-latest
needs: [release]

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ needs.release.outputs.tag }}

- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build

- name: Build package
run: |
python -m build

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist-${{ needs.release.outputs.version }}
path: dist/*
retention-days: 90

notify:
name: Notify Release Completion
runs-on: ubuntu-latest
needs: [release, build]
if: always()

steps:
- name: Release Success
if: needs.release.result == 'success' && needs.build.result == 'success'
run: |
echo "🎉 Release ${{ needs.release.outputs.version }} completed successfully!"
echo "📦 Package built and artifacts uploaded"
echo "🏷️ Git tag: ${{ needs.release.outputs.tag }}"
echo "📋 Release URL: https://github.com/${{ github.repository }}/releases/tag/${{ needs.release.outputs.tag }}"

- name: Release Failed
if: needs.release.result == 'failure' || needs.build.result == 'failure'
run: |
echo "❌ Release failed!"
echo "Release job: ${{ needs.release.result }}"
echo "Build job: ${{ needs.build.result }}"
exit 1
67 changes: 62 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,71 @@
# Python
.venv
__pycache__
*.pyc
*/*.pyc
*.pyo
*.pyd
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
*.pyc
*/*.pyc
.installed.cfg
*.egg

# IDE
.idea
.env
.vscode/
*.swp
*.swo
*~

# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Environment
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# Testing
.coverage
htmlcov/
.pytest_cache/
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.tox/

# Documentation
docs/_build/
site/

# Release files
.bumpversion.cfg.bak
*.bak

# Claude
.claude

# Test data
tests/test_data
if file == '.DS_Store':
continue
Loading