diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml new file mode 100644 index 0000000..2dfcff7 --- /dev/null +++ b/.github/workflows/prepare-release.yml @@ -0,0 +1,67 @@ +name: Prepare release PR + +# Step 1 of the release flow. +# Manually triggered. Bumps the version across setup.py / requirements.txt and +# opens a PR labelled `release`. Merging that PR fires `publish.yml`. + +on: + workflow_dispatch: + inputs: + version: + description: "Release version, e.g. 7.2.2 (sets package version, bundled RavenDB server version, and the ravendb client pin)." + required: true + type: string + +permissions: + contents: write + pull-requests: write + +jobs: + prepare: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Bump version + env: + VERSION: ${{ inputs.version }} + run: | + set -euo pipefail + sed -i -E "s/^RAVENDB_VERSION = \".*\"/RAVENDB_VERSION = \"${VERSION}\"/" setup.py + sed -i -E "s/version=\"[0-9][^\"]*\"/version=\"${VERSION}\"/" setup.py + sed -i -E "s/ravendb~=[0-9][^\"]*/ravendb~=${VERSION}/" setup.py + sed -i -E "s/^ravendb~=.*/ravendb~=${VERSION}/" requirements.txt + + echo "----- setup.py -----" + grep -nE 'RAVENDB_VERSION|version=|ravendb~=' setup.py || true + echo "----- requirements.txt -----" + cat requirements.txt + + if git diff --quiet; then + echo "::error::No version strings changed. Check the sed patterns against setup.py / requirements.txt." + exit 1 + fi + + - name: Create release PR + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + base: ${{ github.event.repository.default_branch }} + branch: release/${{ inputs.version }} + delete-branch: true + commit-message: "Release ${{ inputs.version }}" + title: "Release ${{ inputs.version }}" + labels: release + body: | + Automated release for **ravendb-embedded ${{ inputs.version }}**. + + Bumps `setup.py` (package version, `RAVENDB_VERSION`, `ravendb` pin) and `requirements.txt`. + + > [!WARNING] + > Merging this PR **while the `release` label is set** triggers the + > **Publish to PyPI** workflow, which builds and uploads the package and + > creates the `v${{ inputs.version }}` GitHub release. + + Review the diff (adjust manually if the server version must differ from the + package version), then merge to publish. Remove the `release` label before + merging if you do **not** want to publish. diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..0cb3a8a --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,64 @@ +name: Publish to PyPI + +# Step 2 of the release flow. +# Fires when a PR labelled `release` is merged (the PR opened by prepare-release.yml). +# Also runnable manually as an emergency fallback (publishes whatever is on the branch). + +on: + pull_request: + types: [closed] + workflow_dispatch: + +permissions: + contents: write # create the git tag / GitHub release + +jobs: + publish: + # Only on manual run, or on a merged PR that carried the `release` label. + if: >- + github.event_name == 'workflow_dispatch' || + (github.event.pull_request.merged == true && + contains(github.event.pull_request.labels.*.name, 'release')) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.base.ref || github.ref_name }} + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install build tooling + run: python -m pip install --upgrade pip setuptools wheel twine + + # Order matters: the custom sdist command downloads & unpacks the RavenDB + # server from NuGet; bdist_wheel then bundles those files into the wheel. + - name: Build sdist + wheel + run: python setup.py sdist bdist_wheel + + - name: Read package version + id: ver + run: echo "version=$(python setup.py --version)" >> "$GITHUB_OUTPUT" + + - name: Publish to PyPI + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + run: twine upload --non-interactive --skip-existing dist/* + + - name: Tag & GitHub release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: ${{ steps.ver.outputs.version }} + TARGET: ${{ github.event.pull_request.base.ref || github.ref_name }} + run: | + set -euo pipefail + if gh release view "${VERSION}" >/dev/null 2>&1; then + echo "Release ${VERSION} already exists, skipping." + else + gh release create "${VERSION}" \ + --target "${TARGET}" \ + --title "${VERSION}" \ + --notes "ravendb-embedded ${VERSION} published to PyPI." + fi