docs: Add strict quality standards - no ignoring pre-existing issues … #113
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| permissions: {} | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install UV | |
| uses: astral-sh/setup-uv@v4 | |
| # Temporarily disable cache due to service issues | |
| # with: | |
| # enable-cache: true | |
| - name: Set up Python | |
| run: uv python install 3.13 | |
| - name: Install dependencies | |
| run: uv sync --all-extras | |
| - name: Run full CI pipeline | |
| run: uv run poe ci | |
| release-client: | |
| needs: test | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: release-client | |
| cancel-in-progress: false | |
| permissions: | |
| id-token: write | |
| contents: write | |
| outputs: | |
| released: ${{ steps.release.outputs.released }} | |
| version: ${{ steps.release.outputs.version }} | |
| tag: ${{ steps.release.outputs.tag }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.SEMANTIC_RELEASE_TOKEN }} | |
| - name: Install UV | |
| uses: astral-sh/setup-uv@v4 | |
| # Temporarily disable cache due to service issues | |
| # with: | |
| # enable-cache: true | |
| - name: Set up Python | |
| run: uv python install 3.13 | |
| - name: Install dependencies | |
| run: uv sync --all-extras | |
| - name: Check for client changes | |
| id: check | |
| run: | | |
| # Check if there are any commits with (client) scope or no scope since last client release | |
| # Pattern explicitly matches: feat/fix/perf with no scope OR (client) scope | |
| # Excludes (mcp) and other scopes to prevent incorrect triggers | |
| if git log $(git describe --tags --abbrev=0 --match="client-v*" 2>/dev/null || echo "HEAD~10")..HEAD --pretty=format:"%s" | grep -qE '^(feat|fix|perf)(:|\\(client\\):)'; then | |
| echo "has_changes=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "has_changes=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Python Semantic Release (Client) | |
| if: steps.check.outputs.has_changes == 'true' | |
| id: release | |
| uses: python-semantic-release/python-semantic-release@v9.15.2 | |
| with: | |
| github_token: ${{ secrets.SEMANTIC_RELEASE_TOKEN }} | |
| root_options: -vv | |
| - name: Build client package | |
| if: steps.release.outputs.released == 'true' | |
| run: | | |
| uv build | |
| mkdir -p client-dist | |
| cp dist/*.whl dist/*.tar.gz client-dist/ | |
| - name: Upload client artifacts | |
| if: steps.release.outputs.released == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist-client | |
| path: client-dist/ | |
| release-mcp: | |
| needs: [test, release-client] | |
| # Run if: (1) there are MCP changes OR (2) client was released (MCP needs new client version) | |
| if: always() && needs.test.result == 'success' | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: release-mcp | |
| cancel-in-progress: false | |
| permissions: | |
| id-token: write | |
| contents: write | |
| outputs: | |
| released: ${{ steps.release.outputs.released }} | |
| version: ${{ steps.release.outputs.version }} | |
| tag: ${{ steps.release.outputs.tag }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.SEMANTIC_RELEASE_TOKEN }} | |
| - name: Install UV | |
| uses: astral-sh/setup-uv@v4 | |
| # Temporarily disable cache due to service issues | |
| # with: | |
| # enable-cache: true | |
| - name: Set up Python | |
| run: uv python install 3.13 | |
| - name: Install dependencies | |
| run: uv sync --all-extras | |
| - name: Check for MCP changes or client release | |
| id: check | |
| run: | | |
| # Check if there are any commits with (mcp) scope since last mcp release | |
| # This workflow-level check determines if semantic-release should even run | |
| # NOTE: This regex is intentionally strict—only MCP-scoped commits (e.g., feat(mcp):, fix(mcp):, perf(mcp):) | |
| # will trigger an MCP release. This is consistent with the documented release strategy: | |
| # MCP releases are triggered by MCP-only changes, or when the client is released (checked separately below). | |
| if git log $(git describe --tags --abbrev=0 --match="mcp-v*" 2>/dev/null || echo "HEAD~10")..HEAD --pretty=format:"%s" | grep -qE '^(feat|fix|perf)\(mcp\):'; then | |
| has_mcp_changes=true | |
| else | |
| has_mcp_changes=false | |
| fi | |
| echo "has_mcp_changes=${has_mcp_changes}" >> $GITHUB_OUTPUT | |
| # Check if client was released (MCP needs to pick up new client version) | |
| if [ "${{ needs.release-client.outputs.released }}" == "true" ]; then | |
| echo "client_released=true" >> $GITHUB_OUTPUT | |
| echo "should_release=true" >> $GITHUB_OUTPUT | |
| elif [ "${has_mcp_changes}" == "true" ]; then | |
| echo "client_released=false" >> $GITHUB_OUTPUT | |
| echo "should_release=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "client_released=false" >> $GITHUB_OUTPUT | |
| echo "should_release=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Update MCP client dependency | |
| if: steps.check.outputs.client_released == 'true' | |
| run: | | |
| # Install tomli-w for TOML writing | |
| uv pip install tomli-w | |
| # Update stocktrim-openapi-client dependency to use new version | |
| cat > update_client_dep.py << 'EOF' | |
| import tomllib | |
| import tomli_w | |
| import sys | |
| client_version = sys.argv[1] | |
| with open('stocktrim_mcp_server/pyproject.toml', 'rb') as f: | |
| data = tomllib.load(f) | |
| # Update client dependency to specific version | |
| for i, dep in enumerate(data['project']['dependencies']): | |
| if dep.startswith('stocktrim-openapi-client'): | |
| data['project']['dependencies'][i] = f'stocktrim-openapi-client=={client_version}' | |
| break | |
| # Remove workspace source override for PyPI release | |
| if 'tool' in data and 'uv' in data['tool'] and 'sources' in data['tool']['uv']: | |
| if 'stocktrim-openapi-client' in data['tool']['uv']['sources']: | |
| del data['tool']['uv']['sources']['stocktrim-openapi-client'] | |
| with open('stocktrim_mcp_server/pyproject.toml', 'wb') as f: | |
| tomli_w.dump(data, f) | |
| print(f'Updated MCP client dependency to {client_version}') | |
| EOF | |
| uv run python update_client_dep.py "${{ needs.release-client.outputs.version }}" | |
| # Commit the dependency update | |
| # Note: This chore(mcp) commit won't itself trigger a version bump (default_bump_level=0 for chore commits) | |
| # The subsequent semantic-release step will pick up this change and include it in the release | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add stocktrim_mcp_server/pyproject.toml | |
| git diff --cached --quiet || git commit -m "chore(mcp): update client dependency to v${{ needs.release-client.outputs.version }}" | |
| git push | |
| - name: Python Semantic Release (MCP) | |
| if: steps.check.outputs.should_release == 'true' | |
| id: release | |
| uses: python-semantic-release/python-semantic-release@v9.15.2 | |
| with: | |
| github_token: ${{ secrets.SEMANTIC_RELEASE_TOKEN }} | |
| root_options: -vv | |
| directory: stocktrim_mcp_server | |
| - name: Build MCP server package | |
| if: steps.release.outputs.released == 'true' | |
| run: | | |
| rm -rf dist/ | |
| uv build --package stocktrim-mcp-server | |
| mkdir -p mcp-dist | |
| cp dist/*.whl dist/*.tar.gz mcp-dist/ | |
| - name: Upload MCP server artifacts | |
| if: steps.release.outputs.released == 'true' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist-mcp | |
| path: mcp-dist/ | |
| publish-client: | |
| name: Publish Client to PyPI | |
| needs: release-client | |
| if: needs.release-client.outputs.released == 'true' | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: pypi-client | |
| url: https://pypi.org/p/stocktrim-openapi-client | |
| permissions: | |
| id-token: write | |
| steps: | |
| - name: Download client artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist-client | |
| path: dist/ | |
| - name: Publish client to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| attestations: true | |
| publish-mcp: | |
| name: Publish MCP Server to PyPI | |
| needs: release-mcp | |
| if: needs.release-mcp.outputs.released == 'true' | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: pypi-mcp | |
| url: https://pypi.org/p/stocktrim-mcp-server | |
| permissions: | |
| id-token: write | |
| steps: | |
| - name: Download MCP server artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist-mcp | |
| path: dist/ | |
| - name: Publish MCP server to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| attestations: true |