Skip to content

npm annoying

npm annoying #40

name: Publish Python SDK
on:
workflow_dispatch:
release:
types:
- published
push:
branches:
- main
jobs:
preflight:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
publish_needed: ${{ steps.pypi_check.outputs.publish_needed }}
version: ${{ steps.meta.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Read package metadata
id: meta
run: |
python - <<'PY'
import os
import tomllib
with open("bindings/python/pyproject.toml", "rb") as f:
project = tomllib.load(f)["project"]
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as out:
out.write(f"name={project['name']}\n")
out.write(f"version={project['version']}\n")
PY
- name: Check if version is already on PyPI
id: pypi_check
run: |
python - <<'PY'
import json
import os
import tomllib
import urllib.error
import urllib.request
with open("bindings/python/pyproject.toml", "rb") as f:
project = tomllib.load(f)["project"]
name = project["name"]
version = project["version"]
url = f"https://pypi.org/pypi/{name}/json"
publish_needed = True
try:
with urllib.request.urlopen(url, timeout=15) as resp:
payload = json.load(resp)
releases = payload.get("releases", {})
publish_needed = version not in releases
except urllib.error.HTTPError as e:
if e.code != 404:
raise
print(f"{name} {version} publish_needed={publish_needed}")
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as out:
out.write(f"publish_needed={'true' if publish_needed else 'false'}\n")
PY
build_native:
needs: preflight
if: needs.preflight.outputs.publish_needed == 'true'
strategy:
fail-fast: false
matrix:
include:
- os: windows-2022
artifact: win32-x64
- os: ubuntu-22.04
artifact: linux-x64
- os: macos-15-intel
artifact: darwin-x64
- os: macos-14
artifact: darwin-arm64
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Setup MSYS2 (Windows onionrelay toolchain)
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
mingw-w64-x86_64-toolchain
mingw-w64-x86_64-openssl
mingw-w64-x86_64-libevent
mingw-w64-x86_64-xz
mingw-w64-x86_64-zstd
mingw-w64-x86_64-zlib
autoconf
automake
libtool
make
pkgconf
gettext
- name: Install Linux dependencies (onionrelay)
if: runner.os == 'Linux'
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential \
pkg-config \
libevent-dev \
libssl-dev \
zlib1g-dev \
liblzma-dev \
libzstd-dev \
automake \
libtool \
autoconf \
gettext
- name: Install macOS dependencies (onionrelay)
if: runner.os == 'macOS'
shell: bash
run: |
brew update
brew install \
pkg-config \
libevent \
openssl@3 \
xz \
zstd \
automake \
libtool \
autoconf \
gettext
- name: Build native core (Windows)
if: runner.os == 'Windows'
shell: powershell
run: .\scripts\build_p4_core.ps1
- name: Build native core (Linux/macOS)
if: runner.os != 'Windows'
shell: bash
run: |
chmod +x scripts/build_p4_core_unix.sh
./scripts/build_p4_core_unix.sh
- name: Build onionrelay (Windows)
if: runner.os == 'Windows'
shell: powershell
env:
MSYS2_ROOT: ${{ runner.temp }}\\msys64
run: .\build_onionrelay_windows.ps1
- name: Build onionrelay (Linux/macOS)
if: runner.os != 'Windows'
shell: bash
run: |
chmod +x scripts/build_onionrelay_unix.sh
./scripts/build_onionrelay_unix.sh "${GITHUB_WORKSPACE}/dist" onionrelay
- name: Stage bundled payload (Windows)
if: runner.os == 'Windows'
shell: powershell
run: |
New-Item -ItemType Directory -Force -Path out\win32-x64\core | Out-Null
New-Item -ItemType Directory -Force -Path out\win32-x64\onionrelay | Out-Null
Copy-Item dist\p4_core\windows-x64\p4_core.dll out\win32-x64\core\p4_core.dll -Force
Copy-Item onionrelay_src\src\app\onionrelay.exe out\win32-x64\onionrelay\onionrelay.exe -Force
$dlls = Get-ChildItem onionrelay_src\src\app\*.dll -ErrorAction SilentlyContinue
foreach ($dll in $dlls) {
Copy-Item $dll.FullName out\win32-x64\onionrelay\ -Force
}
- name: Stage bundled payload (Linux)
if: runner.os == 'Linux'
shell: bash
run: |
mkdir -p out/linux-x64/core
mkdir -p out/linux-x64/onionrelay
cp -f dist/p4_core/linux-x64/libp4_core.so out/linux-x64/core/libp4_core.so
cp -f dist/onionrelay out/linux-x64/onionrelay/onionrelay
chmod +x out/linux-x64/onionrelay/onionrelay
- name: Stage bundled payload (macOS)
if: runner.os == 'macOS'
shell: bash
run: |
mkdir -p "out/${{ matrix.artifact }}/core"
mkdir -p "out/${{ matrix.artifact }}/onionrelay"
cp -f dist/p4_core/macos/libp4_core.dylib "out/${{ matrix.artifact }}/core/libp4_core.dylib"
cp -f dist/onionrelay "out/${{ matrix.artifact }}/onionrelay/onionrelay"
chmod +x "out/${{ matrix.artifact }}/onionrelay/onionrelay"
- name: Upload native artifact
uses: actions/upload-artifact@v4
with:
name: python-native-${{ matrix.artifact }}
path: out/**
publish:
needs: [preflight, build_native]
if: needs.preflight.outputs.publish_needed == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Download native artifact (Windows x64)
uses: actions/download-artifact@v4
with:
name: python-native-win32-x64
path: tmp_native/win32
- name: Download native artifact (Linux x64)
uses: actions/download-artifact@v4
with:
name: python-native-linux-x64
path: tmp_native/linux
- name: Download native artifact (macOS x64)
uses: actions/download-artifact@v4
with:
name: python-native-darwin-x64
path: tmp_native/darwin-x64
- name: Download native artifact (macOS arm64)
uses: actions/download-artifact@v4
with:
name: python-native-darwin-arm64
path: tmp_native/darwin-arm64
- name: Stage downloaded native payload
shell: bash
run: |
mkdir -p bindings/python/p4_core/native
mkdir -p bindings/python/p4_core/onionrelay
find bindings/python/p4_core/native -mindepth 1 -maxdepth 1 ! -name '__init__.py' ! -name '.gitkeep' -exec rm -rf {} +
find bindings/python/p4_core/onionrelay -mindepth 1 -maxdepth 1 ! -name '.gitkeep' -exec rm -rf {} +
rm -rf bindings/python/p4_core/native/win32-x64
rm -rf bindings/python/p4_core/native/linux-x64
rm -rf bindings/python/p4_core/native/darwin-x64
rm -rf bindings/python/p4_core/native/darwin-arm64
rm -rf bindings/python/p4_core/onionrelay/win32-x64
rm -rf bindings/python/p4_core/onionrelay/linux-x64
rm -rf bindings/python/p4_core/onionrelay/darwin-x64
rm -rf bindings/python/p4_core/onionrelay/darwin-arm64
mkdir -p bindings/python/p4_core/native/win32-x64
mkdir -p bindings/python/p4_core/native/linux-x64
mkdir -p bindings/python/p4_core/native/darwin-x64
mkdir -p bindings/python/p4_core/native/darwin-arm64
mkdir -p bindings/python/p4_core/onionrelay/win32-x64
mkdir -p bindings/python/p4_core/onionrelay/linux-x64
mkdir -p bindings/python/p4_core/onionrelay/darwin-x64
mkdir -p bindings/python/p4_core/onionrelay/darwin-arm64
WIN_SRC="$(find tmp_native/win32 -type f -path '*core/p4_core.dll' | head -n1)"
LIN_SRC="$(find tmp_native/linux -type f -name 'libp4_core.so' | head -n1)"
DARWIN_X64="$(find tmp_native/darwin-x64 -type f -name 'libp4_core.dylib' | head -n1)"
DARWIN_ARM="$(find tmp_native/darwin-arm64 -type f -name 'libp4_core.dylib' | head -n1)"
WIN_ONION_DIR="$(find tmp_native/win32 -type d -name onionrelay | head -n1)"
LIN_ONION="$(find tmp_native/linux -type f -path '*onionrelay/onionrelay' | head -n1)"
DARWIN_X64_ONION="$(find tmp_native/darwin-x64 -type f -path '*onionrelay/onionrelay' | head -n1)"
DARWIN_ARM_ONION="$(find tmp_native/darwin-arm64 -type f -path '*onionrelay/onionrelay' | head -n1)"
if [ -z "${WIN_SRC}" ] || [ -z "${LIN_SRC}" ] || [ -z "${DARWIN_ARM}" ] || [ -z "${DARWIN_X64}" ] || [ -z "${WIN_ONION_DIR}" ] || [ -z "${LIN_ONION}" ] || [ -z "${DARWIN_X64_ONION}" ] || [ -z "${DARWIN_ARM_ONION}" ]; then
echo "Failed to locate expected native/onionrelay artifacts."
find tmp_native -maxdepth 5 -type f -print
exit 1
fi
cp -f "${WIN_SRC}" bindings/python/p4_core/native/win32-x64/p4_core.dll
cp -f "${LIN_SRC}" bindings/python/p4_core/native/linux-x64/libp4_core.so
cp -f "${DARWIN_X64}" bindings/python/p4_core/native/darwin-x64/libp4_core.dylib
cp -f "${DARWIN_ARM}" bindings/python/p4_core/native/darwin-arm64/libp4_core.dylib
cp -f "${WIN_ONION_DIR}"/* bindings/python/p4_core/onionrelay/win32-x64/
cp -f "${LIN_ONION}" bindings/python/p4_core/onionrelay/linux-x64/onionrelay
cp -f "${DARWIN_X64_ONION}" bindings/python/p4_core/onionrelay/darwin-x64/onionrelay
cp -f "${DARWIN_ARM_ONION}" bindings/python/p4_core/onionrelay/darwin-arm64/onionrelay
chmod +x bindings/python/p4_core/onionrelay/linux-x64/onionrelay
chmod +x bindings/python/p4_core/onionrelay/darwin-x64/onionrelay
chmod +x bindings/python/p4_core/onionrelay/darwin-arm64/onionrelay
- name: Build wheel + sdist
run: |
python -m pip install --upgrade pip build twine
python -m build bindings/python
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
if [ -z "${TWINE_PASSWORD}" ]; then
echo "PYPI_API_TOKEN secret is missing"
exit 1
fi
twine upload bindings/python/dist/*
skip:
needs: preflight
if: needs.preflight.outputs.publish_needed != 'true'
runs-on: ubuntu-latest
steps:
- run: echo "Version already exists on PyPI; skipping publish."