diff --git a/.gitea/workflows/publish.yml b/.gitea/workflows/publish.yml index b727a7d..8ba0ef5 100644 --- a/.gitea/workflows/publish.yml +++ b/.gitea/workflows/publish.yml @@ -1,14 +1,15 @@ name: publish # Build the Python package with uv and publish it to the self-hosted Gitea PyPI -# registry on a version tag. Gated on lint + tests so a release can never ship -# red. Publishing reuses the existing REGISTRY_TOKEN package secret (the same one -# docker.yml uses to push images); if it is absent the job fails loudly instead -# of publishing anonymously. +# registry on merge. dev -> a dev package (aegis-gitea-mcp-dev, .devN versions); +# main -> the stable package (aegis-gitea-mcp). Gated on lint + tests so a release +# can never ship red. Reuses the REGISTRY_TOKEN package secret (same one docker.yml +# uses); if it is absent the job fails loudly instead of publishing anonymously. on: push: - tags: - - 'v*' + branches: + - dev + - main jobs: # --------------------------------------------------------------------------- @@ -55,6 +56,13 @@ jobs: # --------------------------------------------------------------------------- # 3. Build with uv and publish to the Gitea PyPI registry. + # + # dev -> aegis-gitea-mcp-dev X.Y.Z.dev (always unique) + # main -> aegis-gitea-mcp X.Y.Z (no-op if already there) + # + # The package name + version are patched into pyproject.toml at build time + # only — never committed. The committed file keeps name "aegis-gitea-mcp" + # and version "X.Y.Z". # --------------------------------------------------------------------------- publish: needs: [lint, test] @@ -77,11 +85,37 @@ jobs: REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | if [ -z "${REGISTRY_TOKEN}" ]; then - echo "::error::REGISTRY_TOKEN secret is not set." >&2 - echo "Configure a PAT with write:package as the REGISTRY_TOKEN Actions secret." >&2 + echo "::error::REGISTRY_TOKEN secret is not set. Configure a PAT with write:package." >&2 exit 1 fi + - name: Compute channel (package name + version) + id: chan + shell: bash + run: | + BASE="$(grep -E '^version = ' pyproject.toml | head -1 | sed -E 's/^version = "([^"]+)".*/\1/')" + if [ "${GITHUB_REF_NAME}" = "main" ]; then + PKG_NAME="aegis-gitea-mcp" + PKG_VERSION="${BASE}" + CHANNEL="stable" + else + PKG_NAME="aegis-gitea-mcp-dev" + PKG_VERSION="${BASE}.dev${GITHUB_RUN_NUMBER}" + CHANNEL="dev" + fi + echo "pkg_name=${PKG_NAME}" >> "$GITHUB_OUTPUT" + echo "pkg_version=${PKG_VERSION}" >> "$GITHUB_OUTPUT" + echo "channel=${CHANNEL}" >> "$GITHUB_OUTPUT" + echo "Publishing ${PKG_NAME} ${PKG_VERSION} (${CHANNEL})" + + - name: Patch package name + version (build only, not committed) + shell: bash + run: | + sed -i -E "s/^name = \".*\"/name = \"${{ steps.chan.outputs.pkg_name }}\"/" pyproject.toml + sed -i -E "s/^version = \".*\"/version = \"${{ steps.chan.outputs.pkg_version }}\"/" pyproject.toml + echo "--- patched [project] header ---" + grep -E '^(name|version) = ' pyproject.toml + - name: Build sdist + wheel shell: bash run: uv build @@ -93,7 +127,7 @@ jobs: continue-on-error: true uses: actions/upload-artifact@v4 with: - name: dist + name: dist-${{ steps.chan.outputs.channel }} path: dist/* - name: Publish to Gitea PyPI registry @@ -104,10 +138,13 @@ jobs: # username and the token is the password. REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | + # --check-url makes uv skip files already in the registry, so a main + # push that did not bump the version is a clean no-op instead of a 409. uv publish \ --publish-url https://git.hiddenden.cafe/api/packages/Hiddenden/pypi \ - --username "${GITHUB_ACTOR}" \ - --password "${REGISTRY_TOKEN}" + --check-url https://git.hiddenden.cafe/api/packages/Hiddenden/pypi/simple/ \ + --username "${GITHUB_ACTOR}" \ + --password "${REGISTRY_TOKEN}" # Optional second step to also publish to public PyPI lives behind its own # secret. Intentionally left as a disabled stub — this pass does NOT push