docs(research): add research-9 — extension & plugin systems (acture-s… #48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Triggered on every push to main. Behavior depends on changeset state: | |
| # | |
| # - Pending changesets present → opens (or updates) a "Version Packages" | |
| # PR that bumps versions and writes CHANGELOGs. No publish. | |
| # - No pending changesets AND versions in repo are ahead of the | |
| # registries → publishes the npm packages and the `acture` Python | |
| # client to PyPI. | |
| # - No pending changesets AND versions match the registries → no-op. | |
| # | |
| # Secrets consumed (already configured on the repo): | |
| # - NPM_TOKEN — npm publish auth (set with `npm config set //…/token`). | |
| # - PYPI_PASSWORD — PyPI token (used as TWINE_PASSWORD; username "__token__"). | |
| # - GITHUB_TOKEN — auto-provided; used to open the Version Packages PR. | |
| on: | |
| push: | |
| branches: [main] | |
| # Manual fire from the Actions tab — useful for re-running a failed | |
| # publish (e.g. after rotating NPM_TOKEN or fixing PyPI credentials) | |
| # without having to push a fresh commit to main. | |
| workflow_dispatch: | |
| # Avoid two release runs racing on consecutive merges. | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| id-token: write # reserved for PyPI Trusted Publishers if we adopt it later | |
| jobs: | |
| release: | |
| name: Release | |
| runs-on: ubuntu-latest | |
| # Note: we deliberately do not gate on commit-message content. The | |
| # workflow is idempotent — if there are no pending changesets and | |
| # versions match the registries, it no-ops in a few seconds. Earlier | |
| # versions of this file had `if: github.event.head_commit.message | |
| # != ...` which the GitHub Actions parser rejected at workflow init. | |
| outputs: | |
| published: ${{ steps.changesets.outputs.published }} | |
| published-packages: ${{ steps.changesets.outputs.publishedPackages }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| registry-url: https://registry.npmjs.org | |
| - name: Install | |
| run: pnpm install --frozen-lockfile | |
| # Build BEFORE publish — tsup produces dist/ which packages reference | |
| # in their `files` field. Without this, published tarballs would be | |
| # empty. Build first so subsequent typecheck can resolve workspace | |
| # types out of dist/. | |
| - name: Build | |
| run: pnpm -r --filter "./packages/*" build | |
| # Gate the release on the same checks ci.yml runs. If they fail we | |
| # never publish, even when changesets thinks a publish is queued. | |
| - name: Typecheck | |
| run: pnpm -r --filter "./packages/*" typecheck | |
| - name: Test | |
| run: pnpm -r --filter "./packages/*" test | |
| # changesets/action does one of: | |
| # - opens/updates a "Version Packages" PR if changesets/*.md exist, | |
| # - runs the `publish` script otherwise (which publishes to npm). | |
| - name: Changesets — version PR or publish | |
| id: changesets | |
| uses: changesets/action@v1 | |
| with: | |
| version: pnpm version-packages | |
| publish: pnpm release | |
| commit: "chore(release): bump versions" | |
| title: "chore(release): version packages" | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # `changeset publish` -> `npm publish` reads the .npmrc that | |
| # actions/setup-node generates, which references NODE_AUTH_TOKEN. | |
| # NPM_TOKEN is kept for any tooling that looks for that name. | |
| NPM_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| pypi: | |
| name: Publish acture Python client to PyPI | |
| runs-on: ubuntu-latest | |
| needs: release | |
| # Only run when the upstream npm publish succeeded. | |
| if: needs.release.outputs.published == 'true' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install build tooling | |
| run: python -m pip install --upgrade build twine | |
| - name: Build sdist + wheel | |
| working-directory: python | |
| run: python -m build | |
| - name: Check distribution | |
| working-directory: python | |
| run: python -m twine check dist/* | |
| # If the version on PyPI already matches what's in this commit | |
| # (e.g. PyPI was published earlier but the npm half re-ran), | |
| # `--skip-existing` keeps the workflow green. | |
| - name: Upload to PyPI | |
| working-directory: python | |
| env: | |
| TWINE_USERNAME: __token__ | |
| TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} | |
| run: python -m twine upload --skip-existing dist/* |