diff --git a/.gitea/workflows/publish.yml b/.gitea/workflows/publish.yml new file mode 100644 index 0000000..03e560f --- /dev/null +++ b/.gitea/workflows/publish.yml @@ -0,0 +1,104 @@ +name: CI/CD Pipeline + +on: + push: + branches: ["main"] + tags: ["v*"] # Triggers production deployment whenever a version tag is pushed + pull_request: + branches: ["main"] + +jobs: + # --------------------------------------------------------------------------- + # Stage 1: Quality Control & Automated Verification + # --------------------------------------------------------------------------- + test: + name: Verify Pack Integrity + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install Testing Environment + run: | + python -m pip install --upgrade pip + pip install pytest + + - name: Execute Code Audit + run: python -m pytest tests/ -v + + # --------------------------------------------------------------------------- + # Stage 2: Production Build & Multi-Platform Distribution + # --------------------------------------------------------------------------- + publish: + name: Production Release (PyPI & Gitea) + needs: test + if: startsWith(github.ref, 'refs/tags/v') # Strictly run only for tagged versions + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up Production Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install Modern Build Toolchain + run: | + python -m pip install --upgrade pip + pip install build twine + + - name: Compile Distribution Assets (PEP 517) + # This automatically handles whatever package name is configured inside pyproject.toml + run: python -m build + + - name: Publish Package to PyPI + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} # Uses your org-level token safely + run: twine upload --skip-existing dist/* + + - name: Generate Automated Gitea Release + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const path = require('path'); + + // Extract tag context + const tagName = context.ref.replace('refs/tags/', ''); + + // Create the Gitea Release container + const release = await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: tagName, + name: `Release ${tagName}`, + body: `Automated distribution release for version ${tagName}. Verified by system tests.`, + draft: false, + prerelease: false + }); + + // Read and attach compiled distribution files (.whl and .tar.gz) + const distDir = './dist'; + const files = fs.readdirSync(distDir); + + for (const file of files) { + const filePath = path.join(distDir, file); + const fileData = fs.readFileSync(filePath); + + await github.rest.repos.uploadReleaseAsset({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: release.data.id, + name: file, + data: fileData + }); + console.log(`Successfully attached asset: ${file}`); + }