Skip to content

Development Release #96

Development Release

Development Release #96

name: Development Release
# Manual trigger only - creates GitHub release with artifacts and publishes to PyPI
on:
workflow_dispatch:
inputs:
bump-type:
description: 'How to bump the version'
required: true
type: choice
default: 'prerelease'
options:
- prerelease # 2025.3.2a13 -> 2025.3.2a14
- prepatch # 2025.3.2 -> 2025.3.3a1
- preminor # 2025.3.2 -> 2025.4.0a1
- custom # Use custom-version input
custom-version:
description: 'Custom version (only if bump-type is "custom", e.g., 2025.4.0b1)'
required: false
type: string
env:
DOCKER_IMAGE: gridappsd/gridappsd-python
jobs:
dev-release:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop'
permissions:
contents: write
packages: write
steps:
- name: Verify branch
run: |
echo "Running on branch: ${{ github.ref_name }}"
if [ "${{ github.ref_name }}" != "develop" ]; then
echo "Error: Development releases can only be created from the develop branch."
echo "Current branch: ${{ github.ref_name }}"
exit 1
fi
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Pixi
uses: prefix-dev/setup-pixi@v0.8.1
with:
pixi-version: v0.61.0
- name: Determine version
id: bump-version
run: |
# Get current version from pixi.toml
CURRENT_VERSION=$(grep '^version' pixi.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
echo "Current version: $CURRENT_VERSION"
BUMP_TYPE="${{ inputs.bump-type }}"
if [ "$BUMP_TYPE" == "custom" ]; then
# Use custom version
CUSTOM_VERSION="${{ inputs.custom-version }}"
if [ -z "$CUSTOM_VERSION" ]; then
echo "Error: custom-version is required when bump-type is 'custom'"
exit 1
fi
NEW_VERSION="$CUSTOM_VERSION"
echo "Using custom version: $NEW_VERSION"
else
# Parse version components
# Handle versions like 2025.3.2a13 or 2025.3.2
if [[ $CURRENT_VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(a([0-9]+))?$ ]]; then
MAJOR="${BASH_REMATCH[1]}"
MINOR="${BASH_REMATCH[2]}"
PATCH="${BASH_REMATCH[3]}"
PRE_NUM="${BASH_REMATCH[5]:-0}"
else
echo "Error: Cannot parse version $CURRENT_VERSION"
exit 1
fi
case $BUMP_TYPE in
prerelease)
NEW_PRE=$((PRE_NUM + 1))
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}a${NEW_PRE}"
;;
prepatch)
NEW_PATCH=$((PATCH + 1))
NEW_VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}a1"
;;
preminor)
NEW_MINOR=$((MINOR + 1))
NEW_VERSION="${MAJOR}.${NEW_MINOR}.0a1"
;;
esac
fi
echo "New version: $NEW_VERSION"
echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
echo "NEW_TAG=v$NEW_VERSION" >> $GITHUB_ENV
# Update version in pixi.toml
sed -i "s/^version = \".*\"/version = \"$NEW_VERSION\"/" pixi.toml
# Update version in sub-project pyproject.toml files
sed -i "s/^version = \".*\"/version = \"$NEW_VERSION\"/" gridappsd-python-lib/pyproject.toml
sed -i "s/^version = \".*\"/version = \"$NEW_VERSION\"/" gridappsd-field-bus-lib/pyproject.toml
- name: Update lock file
run: pixi install
- name: Run tests
run: pixi run test-all
- name: Build packages
run: pixi run build
- name: Commit and tag
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git add pixi.toml gridappsd-python-lib/pyproject.toml gridappsd-field-bus-lib/pyproject.toml
git commit -m "Bump version to ${{ env.NEW_VERSION }}"
git tag ${{ env.NEW_TAG }}
git push origin HEAD:${{ github.ref_name }}
git push origin ${{ env.NEW_TAG }}
- name: Publish to PyPI
if: github.repository_owner == 'GRIDAPPSD'
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
run: pixi run publish
- name: Create GitHub Release
uses: ncipollo/release-action@v1.15.0
with:
artifacts: "dist/*.tar.gz,dist/*.whl"
artifactErrorsFailBuild: true
generateReleaseNotes: true
prerelease: true
tag: ${{ env.NEW_TAG }}
name: "Development Release ${{ env.NEW_VERSION }}"
body: |
## Development Release
This is a development/pre-release version published to PyPI.
### Installation
**Via pip (from PyPI):**
```bash
pip install gridappsd-python==${{ env.NEW_VERSION }}
```
**Via pip (from GitHub release):**
```bash
pip install https://github.com/GRIDAPPSD/gridappsd-python/releases/download/${{ env.NEW_TAG }}/gridappsd_python-${{ env.NEW_VERSION }}-py3-none-any.whl
```
**Via Docker:**
```bash
docker pull ${{ env.DOCKER_IMAGE }}:${{ env.NEW_VERSION }}
```
token: ${{ secrets.GITHUB_TOKEN }}
- name: Verify package available on PyPI
if: github.repository_owner == 'GRIDAPPSD'
run: |
for i in $(seq 1 30); do
if pip index versions gridappsd-python 2>/dev/null | grep -q "${{ env.NEW_VERSION }}" || \
pip install --dry-run --no-deps "gridappsd-python==${{ env.NEW_VERSION }}" 2>/dev/null; then
echo "Package gridappsd-python==${{ env.NEW_VERSION }} is available on PyPI"
exit 0
fi
echo "Attempt $i/30: Package not yet available, waiting 10s..."
sleep 10
done
echo "Warning: Package not confirmed on PyPI after 5 minutes, proceeding anyway"
# Docker build and push
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
if: github.repository_owner == 'GRIDAPPSD'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
# Build default image (Python 3.12) with develop tag
- name: Build and push Docker image (Python 3.12 - default)
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.repository_owner == 'GRIDAPPSD' }}
build-args: |
PYTHON_VERSION=3.12
GRIDAPPSD_PYTHON_VERSION==${{ env.NEW_VERSION }}
tags: |
${{ env.DOCKER_IMAGE }}:${{ env.NEW_VERSION }}
${{ env.DOCKER_IMAGE }}:${{ env.NEW_VERSION }}-py312
${{ env.DOCKER_IMAGE }}:develop
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
# Build Python 3.10 variant
- name: Build and push Docker image (Python 3.10)
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.repository_owner == 'GRIDAPPSD' }}
build-args: |
PYTHON_VERSION=3.10
GRIDAPPSD_PYTHON_VERSION==${{ env.NEW_VERSION }}
tags: |
${{ env.DOCKER_IMAGE }}:${{ env.NEW_VERSION }}-py310
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
# Build Python 3.11 variant
- name: Build and push Docker image (Python 3.11)
uses: docker/build-push-action@v6
with:
context: .
push: ${{ github.repository_owner == 'GRIDAPPSD' }}
build-args: |
PYTHON_VERSION=3.11
GRIDAPPSD_PYTHON_VERSION==${{ env.NEW_VERSION }}
tags: |
${{ env.DOCKER_IMAGE }}:${{ env.NEW_VERSION }}-py311
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max