ci: build and publish package to Gitea registry on tag
docker / test (push) Successful in 38s
lint / lint (push) Successful in 45s
docker / lint (push) Successful in 44s
test / test (push) Successful in 44s
docker / docker (push) Successful in 40s
docker / lint (pull_request) Successful in 40s
docker / test (pull_request) Successful in 34s
lint / lint (pull_request) Successful in 41s
test / test (pull_request) Successful in 40s
docker / docker (pull_request) Successful in 37s

Add .gitea/workflows/publish.yml: on a v* tag, gate on the existing lint + test
jobs, then build sdist+wheel with uv and publish to the self-hosted Gitea PyPI
registry using least-privilege Actions secrets (GITEA_PACKAGE_USER /
GITEA_PACKAGE_TOKEN). The job fails loudly when the secrets are absent rather
than publishing anonymously, uploads the built artifacts, and leaves a disabled
public-PyPI stub. Public PyPI is intentionally not published in this pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-27 11:18:07 +02:00
parent 385b442b6f
commit 499bf98d92
2 changed files with 116 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
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 uses least-privilege Gitea Actions secrets; if they are absent
# the job fails loudly instead of publishing anonymously.
on:
push:
tags:
- 'v*'
jobs:
# ---------------------------------------------------------------------------
# 1. Lint: ruff + black + mypy (same gate as the other workflows).
# ---------------------------------------------------------------------------
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
- name: Run lint
run: |
ruff check src tests
ruff format --check src tests
black --check src tests
mypy src
# ---------------------------------------------------------------------------
# 2. Test: pytest with coverage gate.
# ---------------------------------------------------------------------------
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
- name: Run tests
run: pytest --cov=aegis_gitea_mcp --cov-report=term-missing --cov-fail-under=80
# ---------------------------------------------------------------------------
# 3. Build with uv and publish to the Gitea PyPI registry.
# ---------------------------------------------------------------------------
publish:
needs: [lint, test]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Set up uv
uses: astral-sh/setup-uv@v5
- name: Require publish credentials
shell: bash
env:
GITEA_PACKAGE_USER: ${{ secrets.GITEA_PACKAGE_USER }}
GITEA_PACKAGE_TOKEN: ${{ secrets.GITEA_PACKAGE_TOKEN }}
run: |
if [ -z "${GITEA_PACKAGE_USER}" ] || [ -z "${GITEA_PACKAGE_TOKEN}" ]; then
echo "::error::GITEA_PACKAGE_USER / GITEA_PACKAGE_TOKEN secrets are not set." >&2
echo "Configure a least-privilege PAT with write:package as Actions secrets." >&2
exit 1
fi
- name: Build sdist + wheel
shell: bash
run: uv build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/*
- name: Publish to Gitea PyPI registry
shell: bash
env:
GITEA_PACKAGE_USER: ${{ secrets.GITEA_PACKAGE_USER }}
GITEA_PACKAGE_TOKEN: ${{ secrets.GITEA_PACKAGE_TOKEN }}
run: |
uv publish \
--publish-url https://git.hiddenden.cafe/api/packages/Hiddenden/pypi \
--username "${GITEA_PACKAGE_USER}" \
--password "${GITEA_PACKAGE_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
# to public PyPI.
#
# - name: Publish to public PyPI
# if: ${{ secrets.PYPI_TOKEN != '' }}
# shell: bash
# env:
# PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
# run: uv publish --username __token__ --password "${PYPI_TOKEN}"
+1
View File
@@ -253,6 +253,7 @@ Gitea workflows were added under `.gitea/workflows/`:
- `lint.yml`: Ruff + formatting + mypy. - `lint.yml`: Ruff + formatting + mypy.
- `test.yml`: lint + pytest + enforced coverage (`>=80%`). - `test.yml`: lint + pytest + enforced coverage (`>=80%`).
- `docker.yml`: lint+test gated Docker build, SHA tag, `latest` tag on `main`. - `docker.yml`: lint+test gated Docker build, SHA tag, `latest` tag on `main`.
- `publish.yml`: on a `v*` tag, lint+test gated `uv build` + publish the Python package to the Gitea PyPI registry (see `docs/packaging.md`).
## Docker hardening ## Docker hardening