name: Build and Release
permissions:
contents: write # For creating releases
pull-requests: write # For commenting on PRs
id-token: write # For PyPI trusted publishing
on:
push:
tags:
- 'v*'
branches: [ main ]
paths-ignore:
- '**.md'
- 'docs/**'
- '.github/*.md'
- '.github/ISSUE_TEMPLATE/**'
- 'LICENSE*'
- '.readthedocs.yml'
- 'CITATION.cff'
- 'CODE_OF_CONDUCT.md'
- 'CONTRIBUTING.md'
- '**.rst'
- '.hound.yml'
- '.gitignore'
- '.gitmodules'
- '.coveragerc'
- 'codecov.yml'
- '.flake8'
- '.pylintrc'
- 'renovate.json'
release:
types: [published]
pull_request:
branches: [ main ]
paths-ignore:
- '**.md'
- 'docs/**'
- '.github/*.md'
- '.github/ISSUE_TEMPLATE/**'
- 'LICENSE*'
- '.readthedocs.yml'
- 'CITATION.cff'
- 'CODE_OF_CONDUCT.md'
- 'CONTRIBUTING.md'
- '**.rst'
- '.hound.yml'
- '.gitignore'
- '.gitmodules'
- '.coveragerc'
- 'codecov.yml'
- '.flake8'
- '.pylintrc'
- 'renovate.json'
workflow_dispatch:
inputs:
fast-mode:
description: 'Skip building wheels and only run tests'
required: false
default: false
type: boolean
python-version:
description: 'Python version to use for testing'
required: false
default: '3.10'
type: string
os:
description: 'OS to run tests on (only Windows is supported)'
required: false
default: 'windows-latest'
type: choice
options:
- windows-latest
jobs:
# Build and test the package
build-and-test:
name: Build and test on ${{ matrix.os }} with Python ${{ matrix.python-version }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest]
python-version: ['3.10', '3.11', '3.12', "3.13"]
# No exclusions needed as we only support Windows
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: |
**/pyproject.toml
**/requirements*.txt
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install uv
uvx poetry lock
uvx poetry install
- name: Lint
run: |
uvx nox -s lint
- name: Test
run: |
uvx nox -s pytest
- name: Build package
run: |
uvx poetry build
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dist-${{ matrix.os }}-${{ matrix.python-version }}
path: dist/
if-no-files-found: error
# Prepare Release
prepare-release:
name: Prepare Release
needs: [build-and-test]
if: github.event_name == 'release' || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))
runs-on: windows-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
# List all artifacts
- name: List all artifacts
run: Get-ChildItem -Path dist -Recurse -File | Sort-Object FullName
shell: pwsh
- name: Generate Release Notes
id: release_notes
run: |
$VERSION = $env:GITHUB_REF -replace 'refs/tags/', ''
"VERSION=$VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append
"RELEASE_NOTES<<EOF" | Out-File -FilePath $env:GITHUB_ENV -Append
"# Photoshop MCP Server $VERSION" | Out-File -FilePath $env:GITHUB_ENV -Append
"" | Out-File -FilePath $env:GITHUB_ENV -Append
"MCP Server for Photoshop integration using photoshop-python-api." | Out-File -FilePath $env:GITHUB_ENV -Append
"" | Out-File -FilePath $env:GITHUB_ENV -Append
"## What's Changed" | Out-File -FilePath $env:GITHUB_ENV -Append
"* Improved MCP host integration" | Out-File -FilePath $env:GITHUB_ENV -Append
"* Added support for Claude Desktop and Claude Windsurf" | Out-File -FilePath $env:GITHUB_ENV -Append
"* Enhanced error handling" | Out-File -FilePath $env:GITHUB_ENV -Append
"EOF" | Out-File -FilePath $env:GITHUB_ENV -Append
shell: pwsh
# Update release notes
- name: Update Release Notes
uses: softprops/action-gh-release@v2
with:
body: ${{ env.RELEASE_NOTES }}
files: dist/*
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Upload artifacts for PyPI publishing
- name: Upload artifacts for PyPI
uses: actions/upload-artifact@v4
with:
name: pypi-dist
path: dist/
if-no-files-found: error
retention-days: 1
# Publish to PyPI
publish-to-pypi:
name: Publish to PyPI
needs: [prepare-release]
if: github.event_name == 'release' || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Download artifacts for PyPI
uses: actions/download-artifact@v4
with:
name: pypi-dist
path: dist
# List all artifacts
- name: List all artifacts
run: find dist -type f | sort
# Publish to PyPI
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
skip-existing: true
verbose: true