Skip to content
Merged
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
140 changes: 140 additions & 0 deletions .github/workflows/publish-rc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
name: Publish RC Package

on:
workflow_dispatch:

jobs:
publish-rc:
runs-on: ubuntu-latest

permissions:
contents: write # Required for creating tags and releases
id-token: write # Required for trusted publishing to PyPI

steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Connect to Tailscale
uses: tailscale/github-action@d1b6cd204f8dceda5b3eaad7f1f767be390056cd # v4.2.0
with:
oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }}
oauth-secret: ${{ secrets.TS_OAUTH_SECRET }}
tags: tag:ci

# Servers are pinned to production so the staging host never ships in the package.
- name: Fetch and normalise staging OpenAPI spec
env:
STAGING_OPENAPI_URL: ${{ secrets.STAGING_OPENAPI_URL }}
run: |
curl -fsSL "$STAGING_OPENAPI_URL" -o openapi.json
python3 - <<'PY'
import json

with open("openapi.json") as f:
spec = json.load(f)

spec["servers"] = [{"description": "Production", "url": "https://api.reveng.ai"}]

for schema in spec.get("components", {}).get("schemas", {}).values():
if not isinstance(schema, dict) or schema.get("additionalProperties") is not False:
continue
if schema.get("properties"):
schema["additionalProperties"] = True
else:
# Empty-body schemas stay bare, otherwise they generate as
# Dict[str, object] instead of object.
del schema["additionalProperties"]

with open("openapi.json", "w") as f:
json.dump(spec, f)
PY

- name: Compute RC version
id: version
run: |
BASE=$(jq -r '.info.version' openapi.json)
TAGS=$(git ls-remote --tags --refs origin)

# Staging may not be bumped yet; target the next unreleased patch
while echo "$TAGS" | grep -q "refs/tags/${BASE}$"; do
BASE=$(echo "$BASE" | awk -F. -v OFS=. '{$3++; print}')
done

N=$(git ls-remote --tags --refs origin "refs/tags/${BASE}-rc.*" | wc -l)
VERSION="${BASE}-rc.$((N + 1))"

echo "RC version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Generate Python SDK
uses: openapi-generators/openapitools-generator-action@b729d184e6b3459572c37c0e37f88a832e69b552 # v1
with:
generator: python
generator-tag: 'v7.17.0'
openapi-file: openapi.json
config-file: config.yml
template-dir: templates
command-args: |
--additional-properties=packageVersion=${{ steps.version.outputs.version }}

- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
with:
app-id: ${{ secrets.REVENG_APP_ID }}
private-key: ${{ secrets.REVENG_APP_PRIVATE_KEY }}

# The tag points at a detached commit holding the generated SDK; no branch is updated.
- name: Commit, tag and push
env:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
SDK_VERSION: ${{ steps.version.outputs.version }}
STAGING_OPENAPI_URL: ${{ secrets.STAGING_OPENAPI_URL }}
run: |
rm -Rf docs && mv python-client/docs .
rm -Rf revengai && mv python-client/revengai .
rm -Rf README.md && mv python-client/README.md .
rm -Rf python-client openapi.json
echo "$SDK_VERSION" > .sdk-version

STAGING_HOST=$(echo "$STAGING_OPENAPI_URL" | awk -F/ '{print $3}')
if grep -rqF "$STAGING_HOST" .; then
echo "Error: staging host leaked into generated SDK"
exit 1
fi

git config --global user.name "reveng-github[bot]"
git config --global user.email "reveng-github[bot]@users.noreply.github.com"
git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"

git add .
git commit -m "RC SDK ${SDK_VERSION}"
git tag -a "$SDK_VERSION" -m "$SDK_VERSION"
git push origin "$SDK_VERSION"

- name: Create GitHub pre-release
env:
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
SDK_VERSION: ${{ steps.version.outputs.version }}
run: |
gh release create "$SDK_VERSION" \
--title "$SDK_VERSION" \
--notes "$SDK_VERSION" \
--prerelease \
--latest=false \
--verify-tag

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version-file: '.python-version'

- name: Install uv
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0

# uv-dynamic-versioning turns tag vX.Y.Z-rc.N into PEP 440 X.Y.ZrcN
- name: Build and publish package to PyPI
run: |
uv build
uv publish
Loading