From 0e075ef44496c9adeb45acff680fb313b8e6b613 Mon Sep 17 00:00:00 2001 From: Jari Turkia Date: Tue, 29 Sep 2026 18:24:59 +0300 Subject: [PATCH 1/2] ci: Publish to TestPyPI and PyPI with Trusted Publishing Run by hand for TestPyPI; a v tag publishes to PyPI. README links made absolute so they work on the PyPI project page. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/publish.yml | 79 +++++++++++++++++++++++++++++++++++ README.md | 4 +- 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..5f1973f --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,79 @@ +name: Publish + +# Trusted Publishing: PyPI and TestPyPI trust this workflow, so no API token is stored. +# Run by hand (Actions → Publish → Run workflow) → TestPyPI. +# Push a tag v → PyPI. + +on: + push: + tags: ["v*"] + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-python@v6 + with: + python-version: "3.13" + - name: Tag matches the version in pyproject.toml + if: startsWith(github.ref, 'refs/tags/v') + run: | + version=$(python -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])') + if [ "v$version" != "$GITHUB_REF_NAME" ]; then + echo "::error::Tag $GITHUB_REF_NAME does not match version $version in pyproject.toml"; exit 1 + fi + - run: python -m pip install --upgrade build twine + - run: python -m build + - run: twine check --strict dist/* + # The package must never carry the .proto itself, only the stubs generated from it. + - name: No .proto in the package + run: | + for f in dist/*; do + if python -m zipfile -l "$f" 2>/dev/null | grep -q '\.proto$' || \ + tar -tzf "$f" 2>/dev/null | grep -q '\.proto$'; then + echo "::error::$f contains a .proto file"; exit 1 + fi + done + - uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ + + testpypi: + if: github.event_name == 'workflow_dispatch' + needs: build + runs-on: ubuntu-latest + environment: + name: testpypi + url: https://test.pypi.org/project/mfiles-grpc/ + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v5 + with: + name: dist + path: dist/ + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + + pypi: + if: startsWith(github.ref, 'refs/tags/v') + needs: build + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/project/mfiles-grpc/ + permissions: + id-token: write + steps: + - uses: actions/download-artifact@v5 + with: + name: dist + path: dist/ + - uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/README.md b/README.md index b20ffba..8a092dd 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ get/set (`IRPCDeclarativeMetadataStructure`). > **Not a supported public API.** The protocol comes from the M-Files Desktop > client install and can change with any server update. Regenerate the stubs -> (see [Source of the .proto](#source-of-the-proto)) after upgrading, and run the tests. +> (see [Source of the .proto](https://github.com/M-Files/mfiles-grpc-python#source-of-the-proto)) after upgrading, and run the tests. ## Status @@ -285,4 +285,4 @@ Offline; they need no vault. `scripts/live_object_test.py` is the live check. ## License -MIT; see [LICENSE](LICENSE). +MIT; see [LICENSE](https://github.com/M-Files/mfiles-grpc-python/blob/main/LICENSE). From 7a4622aed66111a3d27355e6360cb4c8a058f586 Mon Sep 17 00:00:00 2001 From: Jari Turkia Date: Tue, 29 Sep 2026 21:14:57 +0300 Subject: [PATCH 2/2] ci: Publish without deployment environments Environments are not available in this repository. Only repository admins can create v* tags (ruleset "release tags"), which keeps PyPI releases admin-only. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/publish.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5f1973f..a1b15b8 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,6 +3,8 @@ name: Publish # Trusted Publishing: PyPI and TestPyPI trust this workflow, so no API token is stored. # Run by hand (Actions → Publish → Run workflow) → TestPyPI. # Push a tag v → PyPI. +# Deployment environments are not available in this repository. The "release tags" ruleset +# lets only repository admins create v* tags, so only they can release to PyPI. on: push: @@ -48,9 +50,6 @@ jobs: if: github.event_name == 'workflow_dispatch' needs: build runs-on: ubuntu-latest - environment: - name: testpypi - url: https://test.pypi.org/project/mfiles-grpc/ permissions: id-token: write steps: @@ -66,9 +65,6 @@ jobs: if: startsWith(github.ref, 'refs/tags/v') needs: build runs-on: ubuntu-latest - environment: - name: pypi - url: https://pypi.org/project/mfiles-grpc/ permissions: id-token: write steps: