Skip to content

Resolve workflow to download from gopher-orch repo #9

Resolve workflow to download from gopher-orch repo

Resolve workflow to download from gopher-orch repo #9

name: Publish Python Packages
on:
push:
branches: [br_release]
permissions:
contents: write
env:
# Version is read from pyproject.toml - update with: python scripts/update_version.py <version>
DRY_RUN: 'false'
jobs:
download-binaries:
name: Download gopher-orch binaries
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
version_tag: ${{ steps.version.outputs.version_tag }}
dry_run: ${{ steps.version.outputs.dry_run }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Read version from pyproject.toml
id: version
run: |
# Extract version from pyproject.toml using Python
VERSION=$(python -c "import re; content=open('pyproject.toml').read(); print(re.search(r'version\s*=\s*\"([^\"]+)\"', content).group(1))")
# Convert PEP 440 dev version to tag format
# e.g., 0.1.0.dev20260225132506 -> v0.1.0-20260225-132506
if [[ "$VERSION" =~ ^([0-9]+\.[0-9]+\.[0-9]+)\.dev([0-9]{8})([0-9]{6})$ ]]; then
BASE_VERSION="${BASH_REMATCH[1]}"
DATE="${BASH_REMATCH[2]}"
TIME="${BASH_REMATCH[3]}"
VERSION_TAG="v${BASE_VERSION}-${DATE}-${TIME}"
else
# Fallback for simple versions like 0.1.0
VERSION_TAG="v${VERSION}"
fi
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "version_tag=${VERSION_TAG}" >> $GITHUB_OUTPUT
echo "dry_run=${{ env.DRY_RUN }}" >> $GITHUB_OUTPUT
echo "Version: ${VERSION}"
echo "Version Tag: ${VERSION_TAG}"
- name: Download all release assets
env:
GH_TOKEN: ${{ secrets.GOPHER_ORCH_TOKEN }}
run: |
# Download all assets from the private gopher-orch repo
gh release download ${{ steps.version.outputs.version_tag }} \
-R GopherSecurity/gopher-orch \
-D downloads
# Extract to platform-specific directories
mkdir -p artifacts/linux-x64 artifacts/linux-arm64
mkdir -p artifacts/darwin-x64 artifacts/darwin-arm64
mkdir -p artifacts/win32-x64 artifacts/win32-arm64
tar -xzf downloads/libgopher-orch-linux-x64.tar.gz -C artifacts/linux-x64
tar -xzf downloads/libgopher-orch-linux-arm64.tar.gz -C artifacts/linux-arm64
tar -xzf downloads/libgopher-orch-macos-x64.tar.gz -C artifacts/darwin-x64
tar -xzf downloads/libgopher-orch-macos-arm64.tar.gz -C artifacts/darwin-arm64
unzip -o downloads/libgopher-orch-windows-x64.zip -d artifacts/win32-x64
unzip -o downloads/libgopher-orch-windows-arm64.zip -d artifacts/win32-arm64
- name: List downloaded artifacts
run: |
echo "=== Downloaded artifacts ==="
find artifacts -type f \( -name "*.so" -o -name "*.dylib" -o -name "*.dll" \) | head -20
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: native-binaries
path: artifacts/
retention-days: 1
publish-platform-packages:
name: Publish ${{ matrix.platform }} package
needs: download-binaries
runs-on: ubuntu-latest
strategy:
max-parallel: 1
matrix:
include:
- platform: darwin-arm64
lib_pattern: "*.dylib"
pkg_name: gopher_security_mcp_native_darwin_arm64
- platform: darwin-x64
lib_pattern: "*.dylib"
pkg_name: gopher_security_mcp_native_darwin_x64
- platform: linux-arm64
lib_pattern: "*.so*"
pkg_name: gopher_security_mcp_native_linux_arm64
- platform: linux-x64
lib_pattern: "*.so*"
pkg_name: gopher_security_mcp_native_linux_x64
- platform: win32-arm64
lib_pattern: "*.dll"
pkg_name: gopher_security_mcp_native_win32_arm64
- platform: win32-x64
lib_pattern: "*.dll"
pkg_name: gopher_security_mcp_native_win32_x64
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install build tools
run: |
pip install build twine
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: native-binaries
path: artifacts/
- name: Copy binaries to package
run: |
PKG_DIR="packages/${{ matrix.platform }}/${{ matrix.pkg_name }}/lib"
mkdir -p "$PKG_DIR"
# Copy library files (handle various directory structures)
# Check lib/ directory
if [ -d "artifacts/${{ matrix.platform }}/lib" ]; then
cp artifacts/${{ matrix.platform }}/lib/${{ matrix.lib_pattern }} "$PKG_DIR/" 2>/dev/null || true
fi
# Check bin/ directory (Windows DLLs might be here)
if [ -d "artifacts/${{ matrix.platform }}/bin" ]; then
cp artifacts/${{ matrix.platform }}/bin/${{ matrix.lib_pattern }} "$PKG_DIR/" 2>/dev/null || true
fi
# Check flat structure
cp artifacts/${{ matrix.platform }}/${{ matrix.lib_pattern }} "$PKG_DIR/" 2>/dev/null || true
# List what we copied
echo "=== Package contents for ${{ matrix.platform }} ==="
ls -la "$PKG_DIR/"
- name: Update package version
run: |
cd packages/${{ matrix.platform }}
VERSION="${{ needs.download-binaries.outputs.version }}"
# Update version in pyproject.toml
sed -i "s/version = \".*\"/version = \"${VERSION}\"/" pyproject.toml
# Update version in __init__.py
sed -i "s/__version__ = \".*\"/__version__ = \"${VERSION}\"/" ${{ matrix.pkg_name }}/__init__.py
echo "Updated pyproject.toml:"
cat pyproject.toml
- name: Build package
run: |
cd packages/${{ matrix.platform }}
python -m build
- name: Publish to PyPI
if: needs.download-binaries.outputs.dry_run != 'true'
run: |
cd packages/${{ matrix.platform }}
twine upload --skip-existing dist/* --username __token__ --password ${{ secrets.PYPI_TOKEN }}
- name: Dry run - show package contents
if: needs.download-binaries.outputs.dry_run == 'true'
run: |
cd packages/${{ matrix.platform }}
echo "=== Would publish package ==="
cat pyproject.toml
echo ""
echo "=== Built packages ==="
ls -la dist/
publish-main-package:
name: Publish main package
needs: [download-binaries, publish-platform-packages]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install build tools
run: |
pip install build twine
- name: Verify package version
run: |
VERSION="${{ needs.download-binaries.outputs.version }}"
PKG_VERSION=$(python -c "import re; content=open('pyproject.toml').read(); print(re.search(r'version\s*=\s*\"([^\"]+)\"', content).group(1))")
echo "Expected version: ${VERSION}"
echo "Package version: ${PKG_VERSION}"
if [ "${VERSION}" != "${PKG_VERSION}" ]; then
echo "Version mismatch! Updating pyproject.toml..."
sed -i "s/version = \".*\"/version = \"${VERSION}\"/" pyproject.toml
sed -i "s/__version__ = \".*\"/__version__ = \"${VERSION}\"/" gopher_security_mcp/__init__.py
fi
echo "Final version:"
grep version pyproject.toml
- name: Build package
run: |
python -m build
- name: Publish to PyPI
if: needs.download-binaries.outputs.dry_run != 'true'
run: |
twine upload --skip-existing dist/* --username __token__ --password ${{ secrets.PYPI_TOKEN }}
- name: Dry run - show package info
if: needs.download-binaries.outputs.dry_run == 'true'
run: |
echo "=== Would publish main package ==="
cat pyproject.toml
echo ""
echo "=== Built packages ==="
ls -la dist/
create-release:
name: Create GitHub Release
needs: [download-binaries, publish-main-package]
runs-on: ubuntu-latest
if: needs.download-binaries.outputs.dry_run != 'true'
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate release notes
run: |
VERSION="${{ needs.download-binaries.outputs.version }}"
VERSION_TAG="${{ needs.download-binaries.outputs.version_tag }}"
# Build Information
cat > RELEASE_NOTES.md << EOF
## Build Information
- **Date:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")
- **Commit:** ${{ github.sha }}
- **Version:** ${VERSION}
- **PyPI package:** \`gopher-security-mcp==${VERSION}\`
EOF
# Extract What's Changed from CHANGELOG.md
echo "## What's Changed" >> RELEASE_NOTES.md
echo "" >> RELEASE_NOTES.md
if [ -f "CHANGELOG.md" ]; then
# Extract content from [Unreleased] section (between ## [Unreleased] and next ## [)
sed -n '/^## \[Unreleased\]/,/^## \[/p' CHANGELOG.md | \
grep -v "^## \[" | \
sed '/^$/d' >> RELEASE_NOTES.md || true
# If Unreleased section is empty, try to get the latest version section
if [ ! -s RELEASE_NOTES.md ] || [ $(wc -l < RELEASE_NOTES.md) -le 10 ]; then
echo "" >> RELEASE_NOTES.md
# Get content from the first versioned section
sed -n '/^## \[0-9\]/,/^## \[/p' CHANGELOG.md | \
head -50 | \
grep -v "^## \[" >> RELEASE_NOTES.md || true
fi
else
echo "No CHANGELOG.md found, listing recent commits..." >> RELEASE_NOTES.md
echo "" >> RELEASE_NOTES.md
git log --pretty=format:"* %s (%h)" --no-merges -20 >> RELEASE_NOTES.md || true
fi
# Add full changelog link
PREV_TAG=$(git tag --sort=-creatordate | grep -v "^${VERSION_TAG}$" | head -1)
if [ -n "$PREV_TAG" ]; then
echo "" >> RELEASE_NOTES.md
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG}...${VERSION_TAG}" >> RELEASE_NOTES.md
fi
echo ""
echo "=== Release Notes ==="
cat RELEASE_NOTES.md
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ needs.download-binaries.outputs.version_tag }}
name: gopher-security-mcp ${{ needs.download-binaries.outputs.version_tag }}
body_path: RELEASE_NOTES.md
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}