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
32 changes: 25 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,45 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
lint-and-test:
name: Lint + Test (Python ${{ matrix.python }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python: ["3.11", "3.12"]
python: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup Node (for @archastro/channel-harness + prism)
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 20
cache: npm

- run: npm ci
- run: npm ci --ignore-scripts

- name: Audit JS tooling dependencies
run: npm audit --audit-level=moderate

- name: Setup Python ${{ matrix.python }}
uses: actions/setup-python@v5
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: ${{ matrix.python }}

- name: Install uv
uses: astral-sh/setup-uv@v3
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
version: "0.11.3"
checksum: c0f3236f146e55472663cfbcc9be3042a9f1092275bbe3fe2a56a6cbfd3da5ce
enable-cache: true

- name: Install project + dev deps
run: uv sync --all-extras
run: uv sync --locked --all-extras

- name: Ruff lint
run: uv run ruff check
Expand All @@ -58,3 +66,13 @@ jobs:
run: uv run pytest tests/contract
env:
ARCHASTRO_RUN_CHANNEL_CONTRACT_TESTS: "1"

- name: Build and import wheel
run: |
rm -rf dist
uv build --no-build-isolation
uv export --locked --no-dev --no-emit-project --format requirements.txt --output-file dist/runtime-requirements.txt >/dev/null
uv venv --clear .wheel-smoke
uv pip install --python .wheel-smoke --require-hashes -r dist/runtime-requirements.txt
uv pip install --python .wheel-smoke --no-deps dist/*.whl
.wheel-smoke/bin/python -c "import archastro.platform; import archastro.phx_channel"
97 changes: 97 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: Publish

# Triggered by the tags that release.yml pushes (v*), and reachable via
# workflow_dispatch so release.yml can re-trigger after pushing the tag —
# tags pushed by GITHUB_TOKEN don't themselves trigger workflows.
#
# Authenticates to PyPI via OIDC (Trusted Publishing) — no PYPI_API_TOKEN.
#
# Prereqs (one-time):
# 1. First publish done manually from a laptop (uv publish or twine upload)
# 2. Trusted publisher configured at pypi.org/manage/project/archastro-sdk/
# pointing at this workflow filename (publish.yml) and the `pypi`
# environment used below.

on:
push:
tags:
- 'v*'
workflow_dispatch:

permissions:
contents: write # create GitHub Release
id-token: write # OIDC token for PyPI Trusted Publishing

jobs:
publish:
name: PyPI publish
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/archastro-sdk
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup Python
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: '3.12'

- name: Install uv
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
version: "0.11.3"
checksum: c0f3236f146e55472663cfbcc9be3042a9f1092275bbe3fe2a56a6cbfd3da5ce
enable-cache: true

- name: Install project + dev deps
run: uv sync --locked --all-extras

- name: Resolve version from tag
id: pkg
env:
TAG: ${{ github.ref_name }}
run: |
set -euo pipefail
case "$TAG" in
v*)
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
;;
*)
echo "Unrecognized tag: $TAG (expected v*)" >&2
exit 1
;;
esac

- name: Verify pyproject.toml version matches tag
env:
EXPECTED: ${{ steps.pkg.outputs.version }}
run: |
set -euo pipefail
actual=$(uv run python -c "import tomllib, sys; print(tomllib.loads(open('pyproject.toml','rb').read().decode())['project']['version'])")
if [ "$actual" != "$EXPECTED" ]; then
echo "Version mismatch: tag says $EXPECTED, pyproject.toml says $actual" >&2
exit 1
fi

- name: Build sdist + wheel
run: |
rm -rf dist
uv build --no-build-isolation

- name: Publish to PyPI (Trusted Publishing)
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # release/v1
# Defaults: reads dist/, uses OIDC when id-token: write is set + a
# trusted publisher is configured for this repo + workflow + env.

- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ github.ref_name }}
VERSION: ${{ steps.pkg.outputs.version }}
run: |
set -euo pipefail
gh release create "$TAG" \
--title "archastro-sdk v$VERSION" \
--notes "Published to PyPI: https://pypi.org/project/archastro-sdk/$VERSION/" \
--generate-notes
129 changes: 129 additions & 0 deletions .github/workflows/regenerate-sdk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
name: Regenerate SDK

# Manually trigger from the Actions tab to pull the latest spec from
# archastro-openapi and re-run @archastro/sdk-generator. If anything
# changes, the workflow force-pushes to a stable branch and opens (or
# updates) a PR to main for review.
#
# No build/test step here — the PR's own CI runs them.

on:
workflow_dispatch:
inputs:
openapi_ref:
description: archastro-openapi git ref to pull spec from
required: false
default: main
permissions:
contents: write
pull-requests: write

env:
AUTO_BRANCH: auto/regenerate-sdk

jobs:
regenerate:
name: Regenerate + open PR
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 20
cache: npm

- run: npm ci --ignore-scripts

- name: Audit JS tooling dependencies
run: npm audit --audit-level=moderate

- name: Setup Python
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: '3.12'

- name: Install uv
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5.4.2
with:
version: "0.11.3"
checksum: c0f3236f146e55472663cfbcc9be3042a9f1092275bbe3fe2a56a6cbfd3da5ce
enable-cache: true

- name: Install project + dev deps
# Required because the regen script invokes `uv run ruff ...` to
# normalize formatting on the generated tree.
run: uv sync --locked --all-extras

- name: Regenerate SDK
env:
ARCHASTRO_OPENAPI_REF: ${{ inputs.openapi_ref }}
run: ./scripts/regenerate_sdk.sh

- name: Detect changes
id: diff
run: |
if [ -z "$(git status --porcelain src tests specs)" ]; then
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "No changes from regeneration; nothing to do."
else
echo "changed=true" >> "$GITHUB_OUTPUT"
git status --short src tests specs
fi

- name: Resolve generator version
if: steps.diff.outputs.changed == 'true'
id: gen
run: |
set -euo pipefail
resolved=$(node -p "require('./node_modules/@archastro/sdk-generator/package.json').version")
echo "version=$resolved" >> "$GITHUB_OUTPUT"

- name: Commit + force-push to ${{ env.AUTO_BRANCH }}
if: steps.diff.outputs.changed == 'true'
env:
REF: ${{ inputs.openapi_ref }}
GEN_VERSION: ${{ steps.gen.outputs.version }}
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git checkout -B "$AUTO_BRANCH"
git add src tests specs
git commit -m "chore(sdk): regenerate from archastro-openapi@$REF (generator $GEN_VERSION)"
git push --force-with-lease origin "$AUTO_BRANCH"

- name: Open or update PR
if: steps.diff.outputs.changed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REF: ${{ inputs.openapi_ref }}
GEN_VERSION: ${{ steps.gen.outputs.version }}
run: |
set -euo pipefail
file_count=$(git diff --name-only HEAD~1 HEAD -- src tests specs | wc -l | tr -d ' ')
body=$(cat <<EOF
Automated SDK regeneration.

- **archastro-openapi ref**: \`$REF\`
- **generator version**: \`$GEN_VERSION\` from package-lock.json
- **changed files**: $file_count

Review the diff carefully — generator output changes can be subtle. The PR's CI will run lint + tests.
EOF
)

existing=$(gh pr list --head "$AUTO_BRANCH" --state open --json number --jq '.[0].number // empty')
if [ -n "$existing" ]; then
echo "Updating PR #$existing"
gh pr edit "$existing" --body "$body"
else
echo "Opening new PR"
gh pr create \
--base main \
--head "$AUTO_BRANCH" \
--title "chore(sdk): regenerate from openapi@$REF" \
--body "$body"
fi
Loading
Loading