From 1d4c8a832f5a06236c4580cbc2e6bade77fe0daa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:23:31 +0100 Subject: [PATCH] chore(template): sync from mcp-ecosystem --- .github/dependabot.yml | 19 +--- .github/workflows/ci.yml | 42 +++++--- .github/workflows/dependabot-auto-merge.yml | 39 ++++++++ .github/workflows/pr-title.yml | 6 +- .github/workflows/release.yml | 103 +++++++------------- .github/workflows/security.yml | 14 +-- pyproject.toml | 2 +- 7 files changed, 114 insertions(+), 111 deletions(-) create mode 100644 .github/workflows/dependabot-auto-merge.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3dcca8e..833f615 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,23 +5,10 @@ updates: schedule: interval: "weekly" groups: - production-dependencies: - patterns: - - "*" - exclude-patterns: - - "pytest*" - - "ruff" + runtime-dependencies: + dependency-type: "production" dev-dependencies: - patterns: - - "pytest*" - - "ruff" + dependency-type: "development" commit-message: prefix: "chore(deps)" open-pull-requests-limit: 10 - - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - commit-message: - prefix: "chore(deps)" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0ae7874..32d4eac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,33 +1,45 @@ name: CI on: - push: - branches: [main] pull_request: branches: [main] + push: + branches: [main] + workflow_dispatch: jobs: test: runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.11", "3.12"] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v6 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 with: - python-version: "3.11" - - - name: Install uv - uses: astral-sh/setup-uv@v8.1.0 + python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - uv venv - uv pip install -e ".[dev]" + python -m pip install --upgrade pip + pip install -e ".[dev]" - - name: Run linter - run: uv run ruff check . + - name: Lint with ruff + run: | + pip install ruff + ruff check . + ruff format --check . + + - name: Test with pytest + run: | + pip install pytest pytest-asyncio pytest-cov + pytest --cov=src --cov-report=xml - - name: Run tests - run: uv run pytest tests/ -v + - name: Upload coverage + uses: codecov/codecov-action@v4 + with: + files: coverage.xml + continue-on-error: true diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml new file mode 100644 index 0000000..8d205b8 --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yml @@ -0,0 +1,39 @@ +name: Dependabot auto-merge + +on: + pull_request_target: + types: + - opened + - reopened + - synchronize + - ready_for_review + +permissions: + contents: write + pull-requests: write + +jobs: + auto-merge: + if: github.actor == 'dependabot[bot]' + runs-on: ubuntu-latest + steps: + - name: Fetch Dependabot metadata + id: meta + uses: dependabot/fetch-metadata@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Approve and enable auto-merge + if: | + steps.meta.outputs.update-type != 'version-update:semver-major' || + steps.meta.outputs.package-ecosystem == 'github_actions' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_URL: ${{ github.event.pull_request.html_url }} + run: | + CURRENT_LOGIN="$(gh api user --jq .login)" + ALREADY_APPROVED="$(gh api "repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews" --jq '[.[] | select(.user.login == "'"$CURRENT_LOGIN"'" and .state == "APPROVED")] | length')" + if [ "$ALREADY_APPROVED" -eq 0 ]; then + gh pr review --approve "$PR_URL" + fi + gh pr merge --auto --squash "$PR_URL" diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index a31952c..5501b91 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -27,9 +27,9 @@ jobs: exit 0 fi - echo "PR title must use Conventional Commits so squash-merge commits on main stay clean." + echo "PR title must use Conventional Commits so squash-merge commits on main have clean, consistent messages." echo "Allowed prefixes: feat, fix, docs, chore, refactor, test, perf, build, ci, revert" echo "Examples:" - echo " feat: add desktop profile writer" - echo " fix(profile): preserve native image paths" + echo " fix: harden push approval auth flow" + echo " feat(auth): add TOTP support" exit 1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c4572c1..201ecb4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,112 +1,75 @@ -name: Release Please +# Release workflow for Python packages +# +# How it works: +# 1. Create a git tag (e.g., v1.0.0) +# 2. Push the tag to trigger this workflow +# 3. Workflow builds and publishes to PyPI using Trusted Publishing +# +# PyPI Trusted Publishing: +# No API tokens needed! Configure at: +# https://pypi.org/manage/project/{package-name}/settings/publishing/ +# Add this repository as a trusted publisher. + +name: Release on: push: - branches: - - main - workflow_dispatch: + tags: + - "v*" permissions: contents: write - issues: write - pull-requests: write + id-token: write jobs: - release-please: - name: Release Please - runs-on: ubuntu-latest - outputs: - release_created: ${{ steps.release.outputs.release_created }} - tag_name: ${{ steps.release.outputs.tag_name }} - sha: ${{ steps.release.outputs.sha }} - steps: - - uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4 - id: release - with: - token: ${{ secrets.RELEASE_PLEASE_TOKEN || github.token }} - config-file: release-please-config.json - manifest-file: .release-please-manifest.json - - build-release: - name: Build Release - needs: release-please - if: ${{ needs.release-please.outputs.release_created == 'true' }} + build: runs-on: ubuntu-latest - permissions: - contents: read steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - with: - ref: ${{ needs.release-please.outputs.sha }} - persist-credentials: false + - uses: actions/checkout@v4 - - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + - uses: actions/setup-python@v5 with: python-version: "3.11" - - name: Install uv - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 - - - name: Install dependencies + - name: Install build dependencies run: | - uv venv - uv pip install -e ".[dev]" - - - name: Run linter - run: uv run ruff check . - - - name: Run tests - run: uv run pytest tests/ -v + python -m pip install --upgrade pip + pip install build - name: Build package - run: uv build --out-dir dist + run: python -m build - name: Upload artifacts - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + uses: actions/upload-artifact@v4 with: name: dist path: dist/ publish-pypi: - name: Publish to PyPI - needs: build-release + needs: build runs-on: ubuntu-latest environment: pypi permissions: id-token: write steps: - name: Download artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + uses: actions/download-artifact@v4 with: name: dist path: dist/ - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 - with: - skip-existing: true + uses: pypa/gh-action-pypi-publish@release/v1 - upload-release-artifacts: - name: Upload Release Artifacts - needs: - - release-please - - build-release - if: ${{ needs.release-please.outputs.release_created == 'true' }} + create-release: + needs: publish-pypi runs-on: ubuntu-latest permissions: contents: write steps: - - name: Download artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: dist - path: dist/ + - uses: actions/checkout@v4 - - name: Upload release artifacts - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v2 + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 with: - tag_name: ${{ needs.release-please.outputs.tag_name }} - files: | - dist/* - fail_on_unmatched_files: true - overwrite_files: true + generate_release_notes: true diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 7b3bc4c..c7d3739 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -18,7 +18,7 @@ jobs: name: CodeQL Analysis runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v4 @@ -35,9 +35,9 @@ jobs: name: Dependency Audit runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - - uses: actions/setup-python@v6 + - uses: actions/setup-python@v5 with: python-version: "3.11" @@ -49,14 +49,15 @@ jobs: - name: Audit dependencies run: pip-audit + continue-on-error: true bandit: name: Bandit Security Scan runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v4 - - uses: actions/setup-python@v6 + - uses: actions/setup-python@v5 with: python-version: "3.11" @@ -64,4 +65,5 @@ jobs: run: pip install bandit - name: Run bandit - run: bandit -r . -x .venv,tests -ll + run: bandit -r src/ -ll + continue-on-error: true diff --git a/pyproject.toml b/pyproject.toml index 97b3127..0a43c22 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", ] dependencies = [ - "mcp[cli]>=1.6.0", + "mcp>=1.0.0", "streamdeck>=0.9.0", "pillow>=10.0.0", ]