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
103 changes: 103 additions & 0 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: publish-pypi

on:
release:
types: [published]
workflow_dispatch:
inputs:
upload:
description: 'Upload to PyPI'
required: false
default: 'true'

jobs:
update-version:
runs-on: ubuntu-latest
permissions:
contents: write
if: github.event_name == 'release'

steps:
- uses: actions/checkout@v5
with:
ref: main

- name: Extract version from tag
id: version
run: |
VERSION=${{ github.event.release.tag_name }}
VERSION=${VERSION#v} # Remove 'v' prefix if present
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Update pyproject.toml
run: |
sed -i 's/version = "[^"]*"/version = "${{ steps.version.outputs.version }}"/' pyproject.toml

- name: Commit and push version update
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add pyproject.toml
git commit -m "chore: bump version to ${{ steps.version.outputs.version }}"
git push origin main

build:
needs: update-version
Comment on lines +44 to +45
Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

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

The 'build' job has an unconditional dependency on 'update-version', but 'update-version' only runs when 'github.event_name == release'. For workflow_dispatch events, the 'build' job will be skipped because its dependency never runs. Either make the 'needs' conditional or ensure 'update-version' runs for both event types.

Copilot uses AI. Check for mistakes.
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v5

Copy link

Copilot AI Oct 27, 2025

Choose a reason for hiding this comment

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

The 'build' job checks out code without specifying a ref, which means it will checkout the default branch state before the version update committed in the 'update-version' job. Add 'ref: main' to ensure the updated pyproject.toml is used for the build.

Suggested change
with:
ref: main

Copilot uses AI. Check for mistakes.
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'

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

- name: Build distribution
run: python -m build

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: distribution
path: dist/

publish:
needs: build
runs-on: ubuntu-latest
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.upload == 'true')

steps:
- uses: actions/checkout@v5

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

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'

- name: Install Twine
run: pip install twine

- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: twine upload dist/* --skip-existing

- name: Create release note
if: github.event_name == 'release'
run: |
echo "✅ Package published to PyPI successfully!"
echo "Version: ${{ github.event.release.tag_name }}"
echo "PyPI URL: https://pypi.org/project/struct/"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ __pycache__
*.log
example_project/
build/*
dist/

# MkDocs generated documentation
site/docs/
Expand Down
74 changes: 74 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
[build-system]
requires = ["setuptools>=65.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "struct"
version = "1.0.0"
description = "A structured data processing tool"
readme = "README.md"
license = {text = "MIT"}
authors = [{name = "httpdss"}]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
requires-python = ">=3.8"
keywords = ["data", "structure", "processing"]

dependencies = [
"PyYAML>=6.0",
"requests>=2.28.0",
"openai>=1.0.0",
"python-dotenv>=0.21.0",
"jinja2>=3.1.0",
"PyGithub>=1.58.0",
"shtab>=1.6.0",
"colorlog>=6.7.0",
"pydantic-ai>=0.1.0",
"fastmcp>=2.0.0",
]

[project.optional-dependencies]
s3 = [
"boto3>=1.26.0",
]
gcs = [
"google-cloud-storage>=2.10.0",
"google-api-core>=2.11.0",
]
cloud = [
"struct[s3]",
"struct[gcs]"
]
dev = [
"pytest>=7.0.0",
"pytest-cov>=4.0.0",
"black>=22.0.0",
"flake8>=4.0.0",
"mypy>=0.990",
]

[project.urls]
Homepage = "https://github.com/httpdss/struct"
Repository = "https://github.com/httpdss/struct.git"

[project.scripts]
struct = "struct_module.main:main"

[tool.setuptools]
include-package-data = true

[tool.setuptools.packages.find]
where = ["."] # Look for packages in root directory
include = ["struct_module*"]

[tool.setuptools.package-data]
struct_module = ["contribs/*.yaml"]
37 changes: 23 additions & 14 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
PyYAML
requests
openai
python-dotenv
jinja2
PyGithub
shtab
colorlog
boto3
google-cloud
google-api-core
cachetools
pydantic-ai
fastmcp>=2.0
# Core dependencies (always installed)
PyYAML>=6.0
requests>=2.28.0
openai>=1.0.0
python-dotenv>=0.21.0
jinja2>=3.1.0
PyGithub>=1.58.0
shtab>=1.6.0
colorlog>=6.7.0
pydantic-ai>=0.1.0
fastmcp>=2.0.0

# Optional: AWS S3 support
# Install with: pip install struct[s3]
# boto3>=1.26.0

# Optional: Google Cloud Storage support
# Install with: pip install struct[gcs]
# google-cloud-storage>=2.10.0
# google-api-core>=2.11.0

# Optional: Both cloud providers
# Install with: pip install struct[cloud]
25 changes: 4 additions & 21 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
from setuptools import setup, find_packages
# This file is maintained only for backwards compatibility.
# Configuration is now in pyproject.toml (PEP 517/518).
from setuptools import setup

def parse_requirements(filename):
with open(filename, 'r') as file:
lines = file.readlines()
return [line.strip() for line in lines if line and not line.startswith('#')]

setup(
name='struct',
version='1.0.0',
packages=find_packages(),
install_requires=parse_requirements('requirements.txt'),
entry_points={
'console_scripts': [
'struct = struct_module.main:main',
],
},
include_package_data=True,
package_data={
'': ['struct_module/contribs/*.yaml'],
},
)
setup()
Loading